blob: 78059214377fbe182256d65ce58b607b066a54fc [file] [log] [blame]
// /*
// * Licensed to the Apache Software Foundation (ASF) under one
// * or more contributor license agreements. See the NOTICE file
// * distributed with this work for additional information
// * regarding copyright ownership. The ASF licenses this file
// * to you under the Apache License, Version 2.0 (the
// * "License"); you may not use this file except in compliance
// * with the License. You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing,
// * software distributed under the License is distributed on an
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// * KIND, either express or implied. See the License for the
// * specific language governing permissions and limitations
// * under the License.
// */
// package org.apache.sysds.runtime.compress.colgroup;
// import java.io.DataInput;
// import java.io.DataOutput;
// import java.io.IOException;
// import java.util.Arrays;
// import java.util.Iterator;
// import org.apache.commons.lang.NotImplementedException;
// import org.apache.sysds.runtime.DMLCompressionException;
// import org.apache.sysds.runtime.DMLScriptException;
// import org.apache.sysds.runtime.compress.utils.AbstractBitmap;
// import org.apache.sysds.runtime.compress.utils.BitmapLossy;
// import org.apache.sysds.runtime.functionobjects.Builtin;
// import org.apache.sysds.runtime.functionobjects.Builtin.BuiltinCode;
// import org.apache.sysds.runtime.functionobjects.KahanPlus;
// import org.apache.sysds.runtime.functionobjects.KahanPlusSq;
// import org.apache.sysds.runtime.functionobjects.ReduceAll;
// import org.apache.sysds.runtime.functionobjects.ReduceCol;
// import org.apache.sysds.runtime.functionobjects.ReduceRow;
// import org.apache.sysds.runtime.matrix.data.IJV;
// import org.apache.sysds.runtime.matrix.data.MatrixBlock;
// import org.apache.sysds.runtime.matrix.operators.AggregateUnaryOperator;
// import org.apache.sysds.runtime.matrix.operators.ScalarOperator;
// public class ColGroupQuan extends ColGroup {
// private static final long serialVersionUID = -9157476271360522008L;
// protected QDictionary _values;
// protected ColGroupQuan() {
// super();
// }
// protected ColGroupQuan(int[] colIndexes, int numRows, AbstractBitmap ubm) {
// // throw new NotImplementedException();
// super(colIndexes, numRows);
// byte[] lossyValues = ((BitmapLossy)ubm).getValues();
// byte[] values = new byte[numRows * colIndexes.length];
// for(int i = 0; i < lossyValues.length; i++) {
// int[] runs = ubm.getOffsetsList(i).extractValues();
// byte curV = lossyValues[i];
// for(int j = 0; j < ubm.getOffsetsList(i).size(); j++) {
// values[runs[j]] = curV;
// }
// }
// _values = new QDictionary(values, ((BitmapLossy)ubm).getScale());
// }
// protected ColGroupQuan(int[] colIndexes, int numRows, QDictionary values) {
// super(colIndexes, numRows);
// _values = values;
// }
// @Override
// public boolean getIfCountsType() {
// return false;
// }
// private ColGroupQuan(int[] colIndexes, QDictionary values) {
// super(colIndexes, values.getValuesLength() / colIndexes.length);
// this._values = values;
// }
// @Override
// public CompressionType getCompType() {
// return CompressionType.QUAN;
// }
// @Override
// protected ColGroupType getColGroupType() {
// return ColGroupType.QUAN8S;
// }
// @Override
// public void decompressToBlock(MatrixBlock target, int rl, int ru) {
// if(_values == null || _values.getValuesLength() == 0) {
// return;
// }
// // TODO Fix Loop to not multiply
// for(int row = rl; row < ru; row++) {
// for(int colIx = 0; colIx < _colIndexes.length; colIx++) {
// int col = _colIndexes[colIx];
// target.quickSetValue(row, col, _values.getValue(row * colIx + row));
// }
// }
// }
// @Override
// public void decompressToBlock(MatrixBlock target, int[] colIndexTargets) {
// if(_values == null || _values.getValuesLength() == 0) {
// return;
// }
// for(int row = 0; row < _numRows; row++) {
// for(int colIx = 0; colIx < _colIndexes.length; colIx++) {
// int col = _colIndexes[colIx];
// target.quickSetValue(row, col, _values.getValue(row * colIx + row));
// }
// }
// }
// @Override
// public void decompressToBlock(MatrixBlock target, int colpos) {
// if(_values == null || _values.getValuesLength() == 0)
// return;
// double[] c = target.getDenseBlockValues();
// int nnz = 0;
// // TODO Fix for multi col group
// for(int row = 0; row < _numRows; row++) {
// double val = _values.getValue(row);
// if(val != 0) {
// nnz++;
// }
// c[row] = val;
// }
// target.setNonZeros(nnz);
// }
// @Override
// public void write(DataOutput out) throws IOException {
// out.writeInt(_numRows);
// out.writeInt(_colIndexes.length);
// for(int i = 0; i < _colIndexes.length; i++)
// out.writeInt(_colIndexes[i]);
// for(int i = 0; i < _values.getValuesLength() ; i++)
// out.writeByte(_values.getValueByte(i));
// out.writeDouble(_values.getScale());
// }
// @Override
// public void readFields(DataInput in) throws IOException {
// _numRows = in.readInt();
// int numCols = in.readInt();
// _colIndexes = new int[numCols];
// for(int i = 0; i < _colIndexes.length; i++)
// _colIndexes[i] = in.readInt();
// byte[] values = new byte[_numRows * numCols];
// for(int i = 0; i < values.length; i++)
// values[i] = in.readByte();
// double scale = in.readDouble();
// _values = new QDictionary(values, scale);
// }
// @Override
// public long getExactSizeOnDisk() {
// long ret = 8; // header
// ret += 8; // Object header of QDictionary
// ret += 4 * _colIndexes.length;
// ret += _values.getValuesLength() ;
// ret += 8; // scale value
// return ret;
// }
// @Override
// public double get(int r, int c) {
// int colIx = Arrays.binarySearch(_colIndexes, c);
// return _values.getValue(r * colIx + r);
// }
// @Override
// public void rightMultByVector(MatrixBlock vector, MatrixBlock result, int rl, int ru) {
// double[] b = ColGroupConverter.getDenseVector(vector);
// double[] c = result.getDenseBlockValues();
// if(_colIndexes.length == 1) {
// double r = b[_colIndexes[0]] * _values.getScale();
// for(int row = rl; row < ru; row++) {
// c[row] += _values.getValueByte(row) * r;
// }
// }
// else {
// // prepare reduced rhs w/ relevant values
// double[] sb = new double[_colIndexes.length];
// for(int j = 0; j < _colIndexes.length; j++) {
// sb[j] = b[_colIndexes[j]];
// }
// int colIx = 0;
// for(int off = 0; off < _values.getValuesLength() ; off += _numRows) {
// double r = _values.getScale() * sb[colIx];
// for(int row = rl; row < ru; row++) {
// c[row] += _values.getValueByte(off + row) * r;
// }
// colIx++;
// }
// }
// }
// @Override
// public void leftMultByRowVector(MatrixBlock vector, MatrixBlock result) {
// double[] a = ColGroupConverter.getDenseVector(vector);
// double[] c = result.getDenseBlockValues();
// for(int row = 0; row < _numRows; row++) {
// double val = _values.getValue(row);
// for(int col = 0; col < _colIndexes.length; col++) {
// double value = val * a[row * col + row];
// c[_colIndexes[col]] += value;
// }
// }
// }
// @Override
// public void leftMultByRowVector(ColGroupDDC vector, MatrixBlock result) {
// throw new NotImplementedException();
// }
// @Override
// public ColGroup scalarOperation(ScalarOperator op) {
// QDictionary res = _values.apply(op);
// return new ColGroupQuan(_colIndexes, res);
// }
// @Override
// public void unaryAggregateOperations(AggregateUnaryOperator op, MatrixBlock result) {
// unaryAggregateOperations(op, result, 0, getNumRows());
// }
// @Override
// public long estimateInMemorySize() {
// return ColGroupSizes.estimateInMemorySizeQuan(getNumRows(), getNumCols());
// }
// @Override
// public void unaryAggregateOperations(AggregateUnaryOperator op, MatrixBlock result, int rl, int ru) {
// if(op.aggOp.increOp.fn instanceof KahanPlus) {
// // Not using KahnObject because we already lost some of that precision anyway in
// // quantization.
// if(op.indexFn instanceof ReduceAll)
// computeSum(result);
// else if(op.indexFn instanceof ReduceCol)
// computeRowSums(result, rl, ru);
// else if(op.indexFn instanceof ReduceRow)
// computeColSums(result);
// }
// else if(op.aggOp.increOp.fn instanceof KahanPlusSq) {
// if(op.indexFn instanceof ReduceAll)
// computeSumSq(result);
// else if(op.indexFn instanceof ReduceCol)
// computeRowSumsSq(result, rl, ru);
// else if(op.indexFn instanceof ReduceRow)
// computeColSumsSq(result);
// }
// else if(op.aggOp.increOp.fn instanceof Builtin &&
// (((Builtin) op.aggOp.increOp.fn).getBuiltinCode() == BuiltinCode.MAX ||
// ((Builtin) op.aggOp.increOp.fn).getBuiltinCode() == BuiltinCode.MIN)) {
// Builtin builtin = (Builtin) op.aggOp.increOp.fn;
// // min and max (reduceall/reducerow over tuples only)
// if(op.indexFn instanceof ReduceAll)
// computeMxx(result, builtin, _zeros);
// else if(op.indexFn instanceof ReduceCol)
// computeRowMxx(result, builtin, rl, ru);
// else if(op.indexFn instanceof ReduceRow)
// computeColMxx(result, builtin, _zeros);
// }
// else {
// throw new DMLScriptException("Unknown UnaryAggregate operator on CompressedMatrixBlock");
// }
// }
// protected void computeSum(MatrixBlock result) {
// long sum = 0L;
// for(int i = 0; i < _values.length(); i++) {
// sum += _values.getValueByte(i);
// }
// result.quickSetValue(0, 0, result.getValue(0, 0) + (double) sum * _values.getScale());
// }
// protected void computeSumSq(MatrixBlock result) {
// double sumsq = 0;
// for(int i = 0; i < _values.length(); i++) {
// double v = _values.getValue(i);
// sumsq += v * v;
// }
// result.quickSetValue(0, 0, result.getValue(0, 0) + sumsq);
// }
// protected void computeRowSums(MatrixBlock result, int rl, int ru) {
// if(_colIndexes.length < 256) {
// short[] rowSums = new short[ru - rl];
// for(int row = rl; row < ru; row++) {
// for(int colIx = 0; colIx < _colIndexes.length; colIx++) {
// rowSums[row - rl] += _values.getValueByte(row * colIx + row);
// }
// }
// for(int row = rl; row < ru; row++) {
// result.quickSetValue(row, 0, result.getValue(row, 0) + rowSums[row - rl] * _values.getScale());
// }
// }
// else {
// throw new NotImplementedException("Not Implemented number of columns in ColGroupQuan row sum");
// }
// }
// protected void computeRowSumsSq(MatrixBlock result, int rl, int ru) {
// // TODO FIX Loop Index calculation!
// if(_colIndexes.length < 256) {
// float[] rowSumSq = new float[ru - rl];
// for(int row = rl; row < ru; row++) {
// for(int colIx = 0; colIx < _colIndexes.length; colIx++) {
// double v = _values.getValue(row * colIx + row);
// rowSumSq[row - rl] += v * v;
// }
// }
// for(int row = rl; row < ru; row++) {
// result.quickSetValue(row, 0, result.getValue(row, 0) + rowSumSq[row - rl]);
// }
// }
// else {
// throw new NotImplementedException("Not Implemented number of columns in ColGroupQuan row sum");
// }
// }
// protected void computeColSums(MatrixBlock result) {
// // TODO AVOID division
// if(_numRows < 256) {
// short[] colSums = new short[_colIndexes.length];
// for(int i = 0; i < _values.length(); i++) {
// colSums[i / _numRows] += _values.getValueByte(i);
// }
// for(int col = 0; col < _colIndexes.length; col++) {
// result.quickSetValue(0, _colIndexes[col], colSums[col] * _values.getScale());
// }
// }
// else if(_numRows < 16777216) { // (Int max + 1) / (short max + 1)
// int[] colSums = new int[_colIndexes.length];
// for(int i = 0; i < _values.length(); i++) {
// colSums[i / _numRows] += _values.getValueByte(i);
// }
// for(int col = 0; col < _colIndexes.length; col++) {
// result.quickSetValue(0, _colIndexes[col], colSums[col] * _values.getScale());
// }
// }
// else {
// double[] colSums = new double[_colIndexes.length];
// for(int i = 0; i < _values.length(); i++) {
// colSums[i / _numRows] += _values.getValueByte(i);
// }
// for(int col = 0; col < _colIndexes.length; col++) {
// result.quickSetValue(0, _colIndexes[col], colSums[col] * _values.getScale());
// }
// }
// }
// protected void computeColSumsSq(MatrixBlock result) {
// // TODO Avoid Division!
// double[] sumsq = new double[_colIndexes.length];
// for(int i = 0; i < _values.length(); i++) {
// double v = _values.getValue(i);
// sumsq[i / _numRows] += v * v;
// }
// for(int col = 0; col < _colIndexes.length; col++) {
// result.quickSetValue(0, _colIndexes[col], sumsq[col]);
// }
// }
// protected void computeRowMxx(MatrixBlock result, Builtin builtin, int rl, int ru) {
// double[] c = result.getDenseBlockValues();
// // TODO: Fix Loop!
// for(int row = rl; row < ru; row++) {
// for(int colIx = 0; colIx < _colIndexes.length; colIx++) {
// double v = _values.getValue(row * colIx + row);
// // System.out.println(v);
// c[row] = builtin.execute(c[row], v);
// }
// }
// }
// protected void computeMxx(MatrixBlock result, Builtin builtin, boolean zeros) {
// double res = 0;
// for(int i = 0; i < _values.length(); i++) {
// res = builtin.execute(res, _values.getValue(i));
// }
// result.quickSetValue(0, 0, res);
// }
// protected void computeColMxx(MatrixBlock result, Builtin builtin, boolean zeros) {
// double[] colRes = new double[_colIndexes.length];
// // TODO FIX INDEX CALCULATION / loop
// for(int i = 0; i < _values.length(); i++) {
// colRes[i / _numRows] = builtin.execute(colRes[i / _numRows], _values.getValue(i));
// }
// for(int col = 0; col < _colIndexes.length; col++) {
// result.quickSetValue(0, _colIndexes[col], colRes[col]);
// }
// }
// @Override
// public Iterator<IJV> getIterator(int rl, int ru, boolean inclZeros, boolean rowMajor) {
// return new QuanValueIterator();
// }
// private class QuanValueIterator implements Iterator<IJV> {
// @Override
// public boolean hasNext() {
// throw new NotImplementedException("Not Implemented");
// }
// @Override
// public IJV next() {
// throw new NotImplementedException("Not Implemented");
// }
// }
// @Override
// public ColGroupRowIterator getRowIterator(int rl, int ru) {
// return new QuanRowIterator();
// }
// private class QuanRowIterator extends ColGroupRowIterator {
// @Override
// public void next(double[] buff, int rowIx, int segIx, boolean last) {
// throw new NotImplementedException("Not Implemented");
// }
// }
// @Override
// public void countNonZerosPerRow(int[] rnnz, int rl, int ru) {
// for(int row = rl; row < ru; row++) {
// int lnnz = 0;
// for(int colIx = 0; colIx < _colIndexes.length; colIx++) {
// lnnz += (_values.getValue(row * colIx + row) != 0) ? 1 : 0;
// }
// rnnz[row - rl] += lnnz;
// }
// }
// @Override
// public MatrixBlock getValuesAsBlock() {
// MatrixBlock target = new MatrixBlock(_numRows, _colIndexes.length, 0.0);
// decompressToBlock(target, _colIndexes);
// return target;
// }
// @Override
// public int[] getCounts() {
// throw new DMLCompressionException(
// "Invalid function call, the counts in Uncompressed Col Group is always 1 for each value");
// }
// @Override
// public int[] getCounts(boolean includeZero) {
// throw new DMLCompressionException(
// "Invalid function call, the counts in Uncompressed Col Group is always 1 for each value");
// }
// @Override
// public double[] getValues() {
// return _values.getValues();
// }
// @Override
// public boolean isLossy() {
// return true;
// }
// }