blob: 4ecde22ff48d453a235e57a60755c09c23140c4c [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.indexes;
import java.io.DataInput;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.sysds.runtime.DMLRuntimeException;
import org.apache.sysds.runtime.compress.DMLCompressionException;
import org.apache.sysds.runtime.compress.colgroup.AColGroup;
import org.apache.sysds.runtime.compress.colgroup.indexes.IColIndex.ColIndexType;
import org.apache.sysds.runtime.compress.utils.IntArrayList;
public interface ColIndexFactory {
public static final Log LOG = LogFactory.getLog(ColIndexFactory.class.getName());
public static IColIndex read(DataInput in) throws IOException {
final ColIndexType t = ColIndexType.values()[in.readByte()];
switch(t) {
case SINGLE:
return new SingleIndex(in.readInt());
case TWO:
return new TwoIndex(in.readInt(), in.readInt());
case ARRAY:
return ArrayIndex.read(in);
case RANGE:
return RangeIndex.read(in);
default:
throw new DMLCompressionException("Failed reading column index of type: " + t);
}
}
public static IColIndex createI(int... indexes) {
return create(indexes);
}
public static IColIndex create(int[] indexes) {
if(indexes.length <= 0)
throw new DMLRuntimeException("Invalid length to create index from : " + indexes.length);
if(indexes.length == 1)
return new SingleIndex(indexes[0]);
else if(indexes.length == 2)
return new TwoIndex(indexes[0], indexes[1]);
else if(RangeIndex.isValidRange(indexes))
return new RangeIndex(indexes[0], indexes[0] + indexes.length);
else
return new ArrayIndex(indexes);
}
public static IColIndex create(IntArrayList indexes) {
final int s = indexes.size();
if(s <= 0)
throw new DMLRuntimeException("Invalid length to create index from " + indexes);
else if(s == 1)
return new SingleIndex(indexes.get(0));
else if(s == 2)
return new TwoIndex(indexes.get(0), indexes.get(1));
else if(RangeIndex.isValidRange(indexes))
return new RangeIndex(indexes.get(0), indexes.get(0) + s);
else
return new ArrayIndex(indexes.extractValues(true));
}
public static IColIndex create(int l, int u) {
if(u - l <= 0)
throw new DMLRuntimeException("Invalid range: " + l + " " + u);
else if(u - 1 == l)
return new SingleIndex(l);
else if(u - 2 == l)
return new TwoIndex(l, l + 1);
else
return new RangeIndex(l, u);
}
public static IColIndex create(int nCol) {
if(nCol <= 0)
throw new DMLRuntimeException("Invalid size of index columns must be above 0");
else if(nCol == 1)
return new SingleIndex(0);
else if(nCol == 2)
return new TwoIndex(0, 1);
else
return new RangeIndex(nCol);
}
public static long estimateMemoryCost(int nCol, boolean contiguous) {
if(nCol == 1)
return SingleIndex.estimateInMemorySizeStatic();
else if(nCol == 2)
return TwoIndex.estimateInMemorySizeStatic();
else if(contiguous)
return RangeIndex.estimateInMemorySizeStatic();
else
return ArrayIndex.estimateInMemorySizeStatic(nCol);
}
public static IColIndex combine(List<AColGroup> gs) {
int numCols = 0;
for(AColGroup g : gs)
numCols += g.getNumCols();
int[] resCols = new int[numCols];
int index = 0;
for(AColGroup g : gs) {
final IIterate it = g.getColIndices().iterator();
while(it.hasNext())
resCols[index++] = it.next();
}
Arrays.sort(resCols);
return create(resCols);
}
public static IColIndex combine(AColGroup a, AColGroup b) {
return combine(a.getColIndices(), b.getColIndices());
}
public static IColIndex combine(IColIndex a, IColIndex b) {
final int numCols = a.size() + b.size();
final int[] resCols = new int[numCols];
int index = 0;
final IIterate ita = a.iterator();
while(ita.hasNext())
resCols[index++] = ita.next();
final IIterate itb = b.iterator();
while(itb.hasNext())
resCols[index++] = itb.next();
Arrays.sort(resCols);
return create(resCols);
}
/**
* Provide a mapping from a to the combined columns shifted over to column positions in the combined.
*
* It is assumed that the caller always input an a that is contained in comb. it is not verified in the call that it
* is correct.
*
* @param comb The combined indexes
* @param a The indexes to look up
* @return A column index mapping.
*/
public static IColIndex getColumnMapping(IColIndex comb, IColIndex a) {
// naive scan entire a, there are options that make this faster depending on what comb look like
// but this is most commonly not relevant.
final int numCols = a.size();
final int[] ret = new int[numCols];
final IIterate itc = comb.iterator();
final IIterate ita = a.iterator();
int index = 0;
while(ita.hasNext()) {
while(itc.v() < ita.v())
itc.next();
ret[index++] = itc.i();
ita.next();
}
return create(ret);
}
}