blob: ff4b5c76de6da2dce16f5276909ada379a10c6bd [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.matrix.data;
import java.util.Iterator;
import org.apache.sysds.runtime.data.SparseBlock;
import org.apache.sysds.runtime.util.LongLongDoubleHashMap;
import org.apache.sysds.runtime.util.LongLongDoubleHashMap.ADoubleEntry;
import org.apache.sysds.runtime.util.LongLongDoubleHashMap.EntryType;
/**
* Ctable map is an abstraction for the hashmap used for ctable's hash group-by
* because this structure is passed through various interfaces. This makes it
* easier to (1) exchange the underlying data structure and (2) maintain statistics
* like max row/column in order to prevent scans during data conversion.
*
*/
public class CTableMap
{
private final LongLongDoubleHashMap _map;
private long _maxRow = -1;
private long _maxCol = -1;
public CTableMap() {
this(EntryType.LONG);
}
public CTableMap(EntryType type) {
_map = new LongLongDoubleHashMap(type);
_maxRow = -1;
_maxCol = -1;
}
public int size() {
return _map.size();
}
public Iterator<ADoubleEntry> getIterator() {
return _map.getIterator();
}
public long getMaxRow() {
return _maxRow;
}
public long getMaxColumn() {
return _maxCol;
}
public void aggregate(long row, long col, double w)
{
//hash group-by for core ctable computation
_map.addValue(row, col, w);
//maintain internal summaries
_maxRow = Math.max(_maxRow, row);
_maxCol = Math.max(_maxCol, col);
}
public MatrixBlock toMatrixBlock(int rlen, int clen)
{
//allocate new matrix block
int nnz = _map.size();
boolean sparse = MatrixBlock.evalSparseFormatInMemory(rlen, clen, nnz);
MatrixBlock mb = new MatrixBlock(rlen, clen, sparse, nnz).allocateBlock();
// copy map values into new matrix block
if( sparse ) //SPARSE <- cells
{
//append cells to sparse target (unordered to avoid shifting)
SparseBlock sblock = mb.getSparseBlock();
Iterator<ADoubleEntry> iter2 = _map.getIterator();
while( iter2.hasNext() ) {
ADoubleEntry e = iter2.next();
double value = e.value;
int rix = (int)e.getKey1();
int cix = (int)e.getKey2();
if( value != 0 && rix<=rlen && cix<=clen ) {
sblock.allocate(rix-1, Math.max(nnz/rlen,1));
sblock.append( rix-1, cix-1, value );
}
}
//sort sparse target representation
mb.sortSparseRows();
mb.recomputeNonZeros();
}
else //DENSE <- cells
{
//directly insert cells into dense target
Iterator<ADoubleEntry> iter = _map.getIterator();
while( iter.hasNext() ) {
ADoubleEntry e = iter.next();
double value = e.value;
int rix = (int)e.getKey1();
int cix = (int)e.getKey2();
if( value != 0 && rix<=rlen && cix<=clen )
mb.quickSetValue( rix-1, cix-1, value );
}
}
return mb;
}
}