org.apache.sysml.runtime.matrix.data.LibMatrixReorg Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of systemml Show documentation
Show all versions of systemml Show documentation
Declarative Machine Learning
/*
* 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.sysml.runtime.matrix.data;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import org.apache.sysml.runtime.DMLRuntimeException;
import org.apache.sysml.runtime.DMLUnsupportedOperationException;
import org.apache.sysml.runtime.functionobjects.DiagIndex;
import org.apache.sysml.runtime.functionobjects.RevIndex;
import org.apache.sysml.runtime.functionobjects.SortIndex;
import org.apache.sysml.runtime.functionobjects.SwapIndex;
import org.apache.sysml.runtime.matrix.mapred.IndexedMatrixValue;
import org.apache.sysml.runtime.matrix.operators.ReorgOperator;
import org.apache.sysml.runtime.util.DataConverter;
import org.apache.sysml.runtime.util.SortUtils;
import org.apache.sysml.runtime.util.UtilFunctions;
/**
* MB:
* Library for selected matrix reorg operations including special cases
* and all combinations of dense and sparse representations.
*
* Current list of supported operations:
* - reshape,
* - r' (transpose),
* - rdiag (diagV2M/diagM2V),
* - rsort (sorting data/indexes)
* - rmempty (remove empty)
* - rexpand (outer/table-seq expansion)
*/
public class LibMatrixReorg
{
public static final boolean SHALLOW_DENSE_VECTOR_TRANSPOSE = true;
public static final boolean SHALLOW_DENSE_ROWWISE_RESHAPE = true;
public static final boolean ALLOW_BLOCK_REUSE = false;
private enum ReorgType {
TRANSPOSE,
REV,
DIAG,
RESHAPE,
SORT,
INVALID,
}
private LibMatrixReorg() {
//prevent instantiation via private constructor
}
/////////////////////////
// public interface //
/////////////////////////
/**
*
* @param op
* @return
*/
public static boolean isSupportedReorgOperator( ReorgOperator op )
{
return (getReorgType(op) != ReorgType.INVALID);
}
/**
*
* @param in
* @param out
* @return
* @throws DMLRuntimeException
*/
public static MatrixBlock reorg( MatrixBlock in, MatrixBlock out, ReorgOperator op )
throws DMLRuntimeException
{
ReorgType type = getReorgType(op);
switch( type )
{
case TRANSPOSE:
return transpose(in, out);
case REV:
return rev(in, out);
case DIAG:
return diag(in, out);
case SORT:
SortIndex ix = (SortIndex) op.fn;
return sort(in, out, ix.getCol(), ix.getDecreasing(), ix.getIndexReturn());
default:
throw new DMLRuntimeException("Unsupported reorg operator: "+op.fn);
}
}
/**
*
* @param in
* @param out
* @return
* @throws DMLRuntimeException
*/
public static MatrixBlock transpose( MatrixBlock in, MatrixBlock out )
throws DMLRuntimeException
{
//Timing time = new Timing(true);
//sparse-safe operation
if( in.isEmptyBlock(false) )
return out;
if( !in.sparse && !out.sparse )
transposeDenseToDense( in, out );
else if( in.sparse && out.sparse )
transposeSparseToSparse( in, out );
else if( in.sparse )
transposeSparseToDense( in, out );
else
transposeDenseToSparse( in, out );
//System.out.println("r' ("+in.rlen+", "+in.clen+", "+in.sparse+", "+out.sparse+") in "+time.stop()+" ms.");
return out;
}
/**
*
* @param in
* @param out
* @return
* @throws DMLRuntimeException
*/
public static MatrixBlock rev( MatrixBlock in, MatrixBlock out )
throws DMLRuntimeException
{
//Timing time = new Timing(true);
//sparse-safe operation
if( in.isEmptyBlock(false) )
return out;
//special case: row vector
if( in.rlen == 1 ) {
out.copy(in);
return out;
}
if( in.sparse )
reverseSparse( in, out );
else
reverseDense( in, out );
//System.out.println("rev ("+in.rlen+", "+in.clen+", "+in.sparse+") in "+time.stop()+" ms.");
return out;
}
/**
*
* @param in
* @param rows1
* @param brlen
* @param out
* @throws DMLRuntimeException
* @throws DMLUnsupportedOperationException
*/
public static void rev( IndexedMatrixValue in, long rlen, int brlen, ArrayList out )
throws DMLRuntimeException, DMLUnsupportedOperationException
{
//input block reverse
MatrixIndexes inix = in.getIndexes();
MatrixBlock inblk = (MatrixBlock) in.getValue();
MatrixBlock tmpblk = rev(inblk, new MatrixBlock(inblk.getNumRows(), inblk.getNumColumns(), inblk.isInSparseFormat()));
//split and expand block if necessary (at most 2 blocks)
if( rlen % brlen == 0 ) //special case: aligned blocks
{
int nrblks = (int)Math.ceil((double)rlen/brlen);
out.add(new IndexedMatrixValue(
new MatrixIndexes(nrblks-inix.getRowIndex()+1, inix.getColumnIndex()), tmpblk));
}
else //general case: unaligned blocks
{
//compute target positions and sizes
long pos1 = rlen - UtilFunctions.computeCellIndex(inix.getRowIndex(), brlen, tmpblk.getNumRows()-1) + 1;
long pos2 = pos1 + tmpblk.getNumRows() - 1;
int ipos1 = UtilFunctions.computeCellInBlock(pos1, brlen);
int iposCut = tmpblk.getNumRows() - ipos1 - 1;
int blkix1 = (int)UtilFunctions.computeBlockIndex(pos1, brlen);
int blkix2 = (int)UtilFunctions.computeBlockIndex(pos2, brlen);
int blklen1 = (int)UtilFunctions.computeBlockSize(rlen, blkix1, brlen);
int blklen2 = (int)UtilFunctions.computeBlockSize(rlen, blkix2, brlen);
//slice first block
MatrixIndexes outix1 = new MatrixIndexes(blkix1, inix.getColumnIndex());
MatrixBlock outblk1 = new MatrixBlock(blklen1, inblk.getNumColumns(), inblk.isInSparseFormat());
MatrixBlock tmp1 = tmpblk.sliceOperations(0, iposCut, 0, tmpblk.getNumColumns()-1, new MatrixBlock());
outblk1.leftIndexingOperations(tmp1, ipos1, outblk1.getNumRows()-1, 0, tmpblk.getNumColumns()-1, outblk1, true);
out.add(new IndexedMatrixValue(outix1, outblk1));
//slice second block (if necessary)
if( blkix1 != blkix2 ) {
MatrixIndexes outix2 = new MatrixIndexes(blkix2, inix.getColumnIndex());
MatrixBlock outblk2 = new MatrixBlock(blklen2, inblk.getNumColumns(), inblk.isInSparseFormat());
MatrixBlock tmp2 = tmpblk.sliceOperations(iposCut+1, tmpblk.getNumRows()-1, 0, tmpblk.getNumColumns()-1, new MatrixBlock());
outblk2.leftIndexingOperations(tmp2, 0, tmp2.getNumRows()-1, 0, tmpblk.getNumColumns()-1, outblk2, true);
out.add(new IndexedMatrixValue(outix2, outblk2));
}
}
}
/**
*
* @param in
* @param out
* @return
* @throws DMLRuntimeException
*/
public static MatrixBlock diag( MatrixBlock in, MatrixBlock out )
throws DMLRuntimeException
{
//Timing time = new Timing(true);
//sparse-safe operation
if( in.isEmptyBlock(false) )
return out;
int rlen = in.rlen;
int clen = in.clen;
if( clen == 1 ){ //diagV2M
diagV2M( in, out );
out.setDiag();
}
else if ( rlen == clen ) //diagM2V
diagM2V( in, out );
else
throw new DMLRuntimeException("Reorg diagM2V requires squared block input. ("+rlen+", "+clen+")");
//System.out.println("rdiag ("+in.rlen+", "+in.clen+", "+in.sparse+", "+out.sparse+") in "+time.stop()+" ms.");
return out;
}
/**
*
*
* @param in
* @param out
* @param by
* @param desc
* @param ixret
* @return
* @throws DMLRuntimeException
*/
public static MatrixBlock sort(MatrixBlock in, MatrixBlock out, int by, boolean desc, boolean ixret)
throws DMLRuntimeException
{
//meta data gathering and preparation
boolean sparse = in.isInSparseFormat();
int rlen = in.rlen;
int clen = in.clen;
out.sparse = (in.sparse && !ixret);
out.nonZeros = ixret ? rlen : in.nonZeros;
//step 1: error handling
if( by <= 0 || clen < by )
throw new DMLRuntimeException("Sort configuration issue: non-existing orderby column: "+by+" ("+rlen+"x"+clen+" input).");
//step 2: empty block / special case handling
if( !ixret ) //SORT DATA
{
if( in.isEmptyBlock(false) ) //EMPTY INPUT BLOCK
return out;
if( !sparse && clen == 1 ) { //DENSE COLUMN VECTOR
//in-place quicksort, unstable (no indexes needed)
out.copy( in ); //dense
Arrays.sort(out.denseBlock);
if( desc )
sortReverseDense(out);
return out;
}
}
else //SORT INDEX
{
if( in.isEmptyBlock(false) ) { //EMPTY INPUT BLOCK
out.allocateDenseBlock(false);
for( int i=0; i0 ) {
Arrays.sort(vix, i, i+len+1);
i += len; //skip processed run
}
}
//step 4: create output matrix (guaranteed non-empty, see step 2)
if( !ixret )
{
//copy input data in sorted order into result
if( !sparse ) //DENSE
{
out.allocateDenseBlock(false);
for( int i=0; i reshape( IndexedMatrixValue in, long rows1, long cols1, int brlen1, int bclen1,
ArrayList out, long rows2, long cols2, int brlen2, int bclen2, boolean rowwise )
throws DMLRuntimeException
{
//prepare inputs
MatrixIndexes ixIn = in.getIndexes();
MatrixBlock mbIn = (MatrixBlock) in.getValue();
//prepare result blocks (no reuse in order to guarantee mem constraints)
Collection rix = computeAllResultBlockIndexes(ixIn, rows1, cols1, brlen1, bclen1, rows2, cols2, brlen2, bclen2, rowwise);
HashMap rblk = createAllResultBlocks(rix, mbIn.nonZeros, rows1, cols1, brlen1, bclen1, rows2, cols2, brlen2, bclen2, rowwise, out);
//basic algorithm
long row_offset = (ixIn.getRowIndex()-1)*brlen1;
long col_offset = (ixIn.getColumnIndex()-1)*bclen1;
if( mbIn.sparse )
reshapeSparse(mbIn, row_offset, col_offset, rblk, rows1, cols1, rows2, cols2, brlen2, bclen2, rowwise);
else //dense
reshapeDense(mbIn, row_offset, col_offset, rblk, rows1, cols1, rows2, cols2, brlen2, bclen2, rowwise);
//prepare output
out = new ArrayList();
for( Entry e : rblk.entrySet() )
out.add(new IndexedMatrixValue(e.getKey(),e.getValue()));
return out;
}
/**
* CP rmempty operation (single input, single output matrix)
*
* @param in
* @param out
* @param rows
* @throws DMLUnsupportedOperationException
* @throws DMLRuntimeException
*/
public static MatrixBlock rmempty(MatrixBlock in, MatrixBlock ret, boolean rows)
throws DMLRuntimeException, DMLUnsupportedOperationException
{
return rmempty(in, ret, rows, null);
}
/**
* CP rmempty operation (single input, single output matrix)
*
* @param in
* @param out
* @param rows
* @throws DMLUnsupportedOperationException
* @throws DMLRuntimeException
*/
public static MatrixBlock rmempty(MatrixBlock in, MatrixBlock ret, boolean rows, MatrixBlock select)
throws DMLRuntimeException, DMLUnsupportedOperationException
{
//check for empty inputs
//(the semantics of removeEmpty are that for an empty m-by-n matrix, the output
//is an empty 1-by-n or m-by-1 matrix because we don't allow matrices with dims 0)
if( in.isEmptyBlock(false) ) {
if( rows )
ret.reset(1, in.clen, in.sparse);
else //cols
ret.reset(in.rlen, 1, in.sparse);
return ret;
}
if( rows )
return removeEmptyRows(in, ret, select);
else //cols
return removeEmptyColumns(in, ret, select);
}
/**
* MR rmempty interface - for rmempty we cannot view blocks independently, and hence,
* there are different CP and MR interfaces.
*
* @param imv1
* @param imv2
* @param out
* @throws DMLRuntimeException
*/
public static void rmempty(IndexedMatrixValue data, IndexedMatrixValue offset, boolean rmRows, long len, long brlen, long bclen, ArrayList outList)
throws DMLRuntimeException
{
//sanity check inputs
if( !(data.getValue() instanceof MatrixBlock && offset.getValue() instanceof MatrixBlock) )
throw new DMLRuntimeException("Unsupported input data: expected "+MatrixBlock.class.getName()+" but got "+data.getValue().getClass().getName()+" and "+offset.getValue().getClass().getName());
if( rmRows && data.getValue().getNumRows()!=offset.getValue().getNumRows()
|| !rmRows && data.getValue().getNumColumns()!=offset.getValue().getNumColumns() ){
throw new DMLRuntimeException("Dimension mismatch between input data and offsets: ["
+data.getValue().getNumRows()+"x"+data.getValue().getNumColumns()+" vs "+offset.getValue().getNumRows()+"x"+offset.getValue().getNumColumns());
}
//compute outputs (at most two output blocks)
HashMap out = new HashMap();
MatrixBlock linData = (MatrixBlock) data.getValue();
MatrixBlock linOffset = (MatrixBlock) offset.getValue();
MatrixIndexes tmpIx = new MatrixIndexes(-1,-1);
if( rmRows ) //margin = "rows"
{
long rlen = len;
long clen = linData.getNumColumns();
for( int i=0; i 0 ) //otherwise empty row
{
//get single row from source block
MatrixBlock src = (MatrixBlock) linData.sliceOperations(
i, i, 0, (int)(clen-1), new MatrixBlock());
long brix = (rix-1)/brlen+1;
long lbrix = (rix-1)%brlen;
tmpIx.setIndexes(brix, data.getIndexes().getColumnIndex());
//create target block if necessary
if( !out.containsKey(tmpIx) ) {
IndexedMatrixValue tmpIMV = new IndexedMatrixValue(new MatrixIndexes(),new MatrixBlock());
tmpIMV.getIndexes().setIndexes(tmpIx);
((MatrixBlock)tmpIMV.getValue()).reset((int)Math.min(brlen, rlen-((brix-1)*brlen)), (int)clen);
out.put(tmpIMV.getIndexes(), tmpIMV);
}
//put single row into target block
((MatrixBlock)out.get(tmpIx).getValue()).copy(
(int)lbrix, (int)lbrix, 0, (int)clen-1, src, false);
}
}
}
else //margin = "cols"
{
long rlen = linData.getNumRows();
long clen = len;
for( int i=0; i 0 ) //otherwise empty row
{
//get single row from source block
MatrixBlock src = (MatrixBlock) linData.sliceOperations(
0, (int)(rlen-1), i, i, new MatrixBlock());
long bcix = (cix-1)/bclen+1;
long lbcix = (cix-1)%bclen;
tmpIx.setIndexes(data.getIndexes().getRowIndex(), bcix);
//create target block if necessary
if( !out.containsKey(tmpIx) ) {
IndexedMatrixValue tmpIMV = new IndexedMatrixValue(new MatrixIndexes(),new MatrixBlock());
tmpIMV.getIndexes().setIndexes(tmpIx);
((MatrixBlock)tmpIMV.getValue()).reset((int)rlen,(int)Math.min(bclen, clen-((bcix-1)*bclen)));
out.put(tmpIMV.getIndexes(), tmpIMV);
}
//put single row into target block
((MatrixBlock)out.get(tmpIx).getValue()).copy(
0, (int)rlen-1, (int)lbcix, (int)lbcix, src, false);
}
}
}
//prepare and return outputs (already in cached values)
for( IndexedMatrixValue imv : out.values() ){
((MatrixBlock)imv.getValue()).recomputeNonZeros();
outList.add(imv);
}
}
/**
* CP rexpand operation (single input, single output)
*
* @param in
* @param ret
* @param rows
* @return
* @throws DMLRuntimeException
* @throws DMLUnsupportedOperationException
*/
public static MatrixBlock rexpand(MatrixBlock in, MatrixBlock ret, double max, boolean rows, boolean cast, boolean ignore)
throws DMLRuntimeException, DMLUnsupportedOperationException
{
//prepare parameters
int lmax = (int)UtilFunctions.toLong(max);
//sanity check for input nnz (incl implicit handling of empty blocks)
if( !ignore && in.getNonZeros() outList)
throws DMLRuntimeException, DMLUnsupportedOperationException
{
//prepare parameters
MatrixIndexes ix = data.getIndexes();
MatrixBlock in = (MatrixBlock)data.getValue();
//execute rexpand operations incl sanity checks
//TODO more robust (memory efficient) implementation w/o tmp block
MatrixBlock tmp = rexpand(in, new MatrixBlock(), max, rows, cast, ignore);
//prepare outputs blocks (slice tmp block into output blocks )
if( rows ) //expanded vertically
{
for( int rl=0; rl 0 )
c[i] = new SparseRow(cnt[i]);
}
//blocking according to typical L2 cache sizes
final int blocksizeI = 128;
final int blocksizeJ = 128;
//temporary array for block boundaries (for preventing binary search)
int[] ix = new int[blocksizeI];
//blocked execution
for( int bi = 0; biMATRIX
{
//note: cache-friendly on a but not on c
for( int j=0, aix=0; jVECTOR
{
//note: cache-friendly on c but not on a
for( int j=0, cix=0; jMATRIX
{
//note: cache-friendly on c but not an a
for( int i=0, cix=0; iVECTOR
{
//note: cache-friendly on a and c; append-only
if( cRows[0] == null )
cRows[0] = new SparseRow(estnnz, cols);
SparseRow crow = cRows[0];
for( int i=0, cix=0; iMATRIX
{
//note: cache-friendly on a but not c; append-only
//long cix because total cells in sparse can be larger than int
long cix = 0;
for( int i=0; iMATRIX
{
//note: cache-friendly on a but not c; append-only
SparseRow arow = aRows[0];
if( arow!=null && !arow.isEmpty() ){
int alen = arow.size();
int[] aix = arow.getIndexContainer();
double[] avals = arow.getValueContainer();
for( int j=0; jMATRIX
{
//note: cache-friendly on a but not c; append&sort, in-place w/o shifts
for( int i=0; iMATRIX
//note: cache-friendly on a and c; append-only
for( int i=0, aix=0; iMATRIX
{
//note: cache-friendly on a but not c; append-only
for( int j=0, aix=0; jMATRIX
{
//note: cache-friendly on c but not a; append-only
for( int i=0; iMATRIX
//note: cache-friendly on a and c
for( int i=0, cix=0; iMATRIX
{
//note: cache-friendly on a but not c
SparseRow arow = aRows[0];
if( arow!=null && !arow.isEmpty() ){
int alen = arow.size();
int[] aix = arow.getIndexContainer();
double[] avals = arow.getValueContainer();
for( int j=0; jMATRIX
{
//note: cache-friendly on a but not c
for( int i=0; i computeAllResultBlockIndexes( MatrixIndexes ixin,
long rows1, long cols1, int brlen1, int bclen1,
long rows2, long cols2, int brlen2, int bclen2, boolean rowwise )
{
HashSet ret = new HashSet();
long nrblk2 = rows2/brlen2 + ((rows2%brlen2!=0)?1:0);
long ncblk2 = cols2/bclen2 + ((cols2%bclen2!=0)?1:0);
long row_offset = (ixin.getRowIndex()-1)*brlen1;
long col_offset = (ixin.getColumnIndex()-1)*bclen1;
if( rowwise ){
for( long i=row_offset; i createAllResultBlocks( Collection rix,
long nnz, long rows1, long cols1, int brlen1, int bclen1,
long rows2, long cols2, int brlen2, int bclen2, boolean rowwise, ArrayList reuse )
{
HashMap ret = new HashMap();
long nBlocks = rix.size();
int count = 0;
//System.out.println("Reuse "+((reuse!=null)?reuse.size():0)+"/"+nBlocks);
for( MatrixIndexes ix : rix )
{
//compute indexes
long bi = ix.getRowIndex();
long bj = ix.getColumnIndex();
int lbrlen = (int) Math.min(brlen2, rows2-(bi-1)*brlen2);
int lbclen = (int) Math.min(bclen2, cols2-(bj-1)*bclen2);
//create result block
int estnnz = (int) (nnz/nBlocks); //force initialcapacity per row to 1, for many blocks
boolean sparse = MatrixBlock.evalSparseFormatInMemory(lbrlen, lbclen, estnnz);
MatrixBlock block = null;
if( ALLOW_BLOCK_REUSE && reuse!=null && !reuse.isEmpty()) {
block = (MatrixBlock) reuse.get(count++).getValue();
block.reset(lbrlen, lbclen, sparse, estnnz);
}
else
block = new MatrixBlock(lbrlen, lbclen, sparse, estnnz);
//System.out.println("create block ("+bi+","+bj+"): "+lbrlen+" "+lbclen);
if( lbrlen<1 || lbclen<1 )
throw new RuntimeException("Computed block dimensions ("+bi+","+bj+" -> "+lbrlen+","+lbclen+") are invalid!");
ret.put(ix, block);
}
return ret;
}
/**
*
* @param in
* @param row_offset
* @param col_offset
* @param rix
* @param rows1
* @param cols1
* @param rows2
* @param cols2
* @param brlen2
* @param bclen2
* @param rowwise
*/
private static void reshapeDense( MatrixBlock in, long row_offset, long col_offset,
HashMap rix,
long rows1, long cols1,
long rows2, long cols2, int brlen2, int bclen2, boolean rowwise )
{
if( in.isEmptyBlock(false) )
return;
int rlen = in.rlen;
int clen = in.clen;
double[] a = in.denseBlock;
//append all values to right blocks
MatrixIndexes ixtmp = new MatrixIndexes();
for( int i=0, aix=0; i rix,
long rows1, long cols1,
long rows2, long cols2, int brlen2, int bclen2, boolean rowwise )
{
if( in.isEmptyBlock(false) )
return;
int rlen = in.rlen;
SparseRow[] aRows = in.sparseRows;
//append all values to right blocks
MatrixIndexes ixtmp = new MatrixIndexes();
for( int i=0; i ci/cj: "+ci+"/"+cj);
ixout.setIndexes(ci, cj);
return ixout;
}
/**
*
* @param in
* @param ret
* @param select
* @return
* @throws DMLRuntimeException
* @throws DMLUnsupportedOperationException
*/
private static MatrixBlock removeEmptyRows(MatrixBlock in, MatrixBlock ret, MatrixBlock select)
throws DMLRuntimeException, DMLUnsupportedOperationException
{
final int m = in.rlen;
final int n = in.clen;
boolean[] flags = null;
int rlen2 = 0;
if(select == null)
{
flags = new boolean[ m ]; //false
//Step 1: scan block and determine non-empty rows
if( in.sparse ) //SPARSE
{
SparseRow[] a = in.sparseRows;
for ( int i=0; i < m; i++ )
if ( a[i] != null && !a[i].isEmpty() ) {
flags[i] = true;
rlen2++;
}
}
else //DENSE
{
double[] a = in.denseBlock;
for(int i=0, aix=0; i= 1 && val <= max )
ret.appendValue((int)(val-1), i+tmpi[j], 1);
}
}
return ret;
}
/**
*
* @param in
* @param ret
* @param max
* @param cast
* @param ignore
* @return
* @throws DMLRuntimeException
*/
private static MatrixBlock rexpandColumns(MatrixBlock in, MatrixBlock ret, int max, boolean cast, boolean ignore)
throws DMLRuntimeException
{
//set meta data
final int rlen = in.rlen;
final int clen = max;
final long nnz = in.nonZeros;
boolean sp = MatrixBlock.evalSparseFormatInMemory(rlen, clen, nnz);
ret.reset(rlen, clen, sp);
//expand input horizontally (input vector likely dense
//but generic implementation for general case)
for( int i=0; i= 1 && val <= max )
ret.appendValue(i, (int)(val-1), 1);
}
return ret;
}
/**
*
* @param in
* @param ixin
* @param tmp
* @param len
*/
private static void copyColVector( MatrixBlock in, int ixin, double[] tmp, int[] tmpi, int len)
{
//copy value array from input matrix
if( in.isEmptyBlock(false) ) {
Arrays.fill(tmp, 0, 0, len);
}
else if( in.sparse ){ //SPARSE
for( int i=0; i
{
private MatrixBlock _mb = null;
private int _col = -1;
public AscRowComparator( MatrixBlock mb, int col )
{
_mb = mb;
_col = col;
}
@Override
public int compare(Integer arg0, Integer arg1)
{
double val0 = _mb.quickGetValue(arg0, _col);
double val1 = _mb.quickGetValue(arg1, _col);
return (val0 < val1 ? -1 : (val0 == val1 ? 0 : 1));
}
}
/**
*
*/
@SuppressWarnings("unused")
private static class DescRowComparator implements Comparator
{
private MatrixBlock _mb = null;
private int _col = -1;
public DescRowComparator( MatrixBlock mb, int col )
{
_mb = mb;
_col = col;
}
@Override
public int compare(Integer arg0, Integer arg1)
{
double val0 = _mb.quickGetValue(arg0, _col);
double val1 = _mb.quickGetValue(arg1, _col);
return (val0 > val1 ? -1 : (val0 == val1 ? 0 : 1));
}
}
}