Skip to content

Commit

Permalink
introduces support for columns of Java float type
Browse files Browse the repository at this point in the history
  • Loading branch information
vmzakharov committed Mar 23, 2024
1 parent c4ce0ee commit ffaf911
Show file tree
Hide file tree
Showing 10 changed files with 480 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -186,65 +186,67 @@ protected RuntimeException notApplicable(DfColumn column)

public int intInitialValue()
{
throw exceptionByKey("AGG_NO_INITIAL_VALUE")
.with("operation", this.getName())
.with("type", "int")
.getUnsupported();
throw this.noInitialValueException(ValueType.INT.toString());
}

public int floatInitialValue()
{
throw this.noInitialValueException(ValueType.FLOAT.toString());
}

public long longInitialValue()
{
throw exceptionByKey("AGG_NO_INITIAL_VALUE")
.with("operation", this.getName())
.with("type", "long")
.getUnsupported();
throw this.noInitialValueException(ValueType.LONG.toString());
}

public double doubleInitialValue()
{
throw exceptionByKey("AGG_NO_INITIAL_VALUE")
.with("operation", this.getName())
.with("type", "double")
.getUnsupported();
throw this.noInitialValueException(ValueType.DOUBLE.toString());
}

public Object objectInitialValue()
{
throw exceptionByKey("AGG_NO_INITIAL_VALUE")
.with("operation", this.getName())
.with("type", "non-numeric")
.getUnsupported();
throw this.noInitialValueException("non-numeric");
}

protected long longAccumulator(long currentAggregate, long newValue)
{
throw exceptionByKey("AGG_NO_ACCUMULATOR")
.with("operation", this.getName())
.with("type", "long")
.getUnsupported();
throw this.unsupportedAccumulatorException(ValueType.LONG.toString());
}

protected int intAccumulator(int currentAggregate, int newValue)
{
throw exceptionByKey("AGG_NO_ACCUMULATOR")
.with("operation", this.getName())
.with("type", "int")
.getUnsupported();
throw this.unsupportedAccumulatorException(ValueType.INT.toString());
}

protected double doubleAccumulator(double currentAggregate, double newValue)
{
throw exceptionByKey("AGG_NO_ACCUMULATOR")
throw this.unsupportedAccumulatorException(ValueType.DOUBLE.toString());
}

protected int floatAccumulator(float currentAggregate, float newValue)
{
throw this.unsupportedAccumulatorException(ValueType.FLOAT.toString());
}

protected Object objectAccumulator(Object currentAggregate, Object newValue)
{
throw this.unsupportedAccumulatorException("object");
}

protected RuntimeException unsupportedAccumulatorException(String typeName)
{
return exceptionByKey("AGG_NO_ACCUMULATOR")
.with("operation", this.getName())
.with("type", "double")
.with("type", typeName)
.getUnsupported();
}

protected Object objectAccumulator(Object currentAggregate, Object newValue)
protected RuntimeException noInitialValueException(String typeName)
{
throw exceptionByKey("AGG_NO_ACCUMULATOR")
throw exceptionByKey("AGG_NO_INITIAL_VALUE")
.with("operation", this.getName())
.with("non-numeric", "long")
.with("type", typeName)
.getUnsupported();
}

Expand Down Expand Up @@ -346,6 +348,16 @@ public void aggregateValueIntoDouble(
this.doubleAccumulator(currentAggregatedValue, this.getDoubleValue(sourceColumn, sourceRowIndex)));
}

public void aggregateValueIntoFloat(
DfFloatColumnStored targetColumn, int targetRowIndex,
DfColumn sourceColumn, int sourceRowIndex)
{
float currentAggregatedValue = targetColumn.getFloat(targetRowIndex);
targetColumn.setFloat(
targetRowIndex,
this.floatAccumulator(currentAggregatedValue, this.getIntValue(sourceColumn, sourceRowIndex)));
}

/**
* by default aggregators treat null values as "poisonous" - that is any null value passed in the aggregator will
* cause the result of the entire aggregation to be null, which is a sensible behavior for most aggregation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import io.github.vmzakharov.ecdataframe.dsl.visitor.TypeInferenceVisitor;
import io.github.vmzakharov.ecdataframe.util.ExpressionParserHelper;
import org.eclipse.collections.api.DoubleIterable;
import org.eclipse.collections.api.FloatIterable;
import org.eclipse.collections.api.IntIterable;
import org.eclipse.collections.api.LongIterable;
import org.eclipse.collections.api.RichIterable;
Expand Down Expand Up @@ -54,7 +55,7 @@
import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;

public class DataFrame
implements DfIterate
implements DfIterate
{
private final String name;
private final MutableMap<String, DfColumn> columnsByName = Maps.mutable.of();
Expand Down Expand Up @@ -136,6 +137,22 @@ public DataFrame addIntColumn(String newColumnName, IntIterable values)
return this;
}

public DataFrame addFloatColumn(String newColumnName)
{
return this.addColumn(newColumnName, ValueType.FLOAT);
}

public DataFrame addFloatColumn(String newColumnName, String expressionAsString)
{
return this.addColumn(newColumnName, ValueType.FLOAT, expressionAsString);
}

public DataFrame addFloatColumn(String newColumnName, FloatIterable values)
{
this.attachColumn(new DfFloatColumnStored(this, newColumnName, values));
return this;
}

public DataFrame addDoubleColumn(String newColumnName)
{
return this.addColumn(newColumnName, ValueType.DOUBLE);
Expand Down Expand Up @@ -439,6 +456,8 @@ private DfColumnStored createStoredColumn(String columnName, ValueType type)
return new DfDecimalColumnStored(this, columnName);
case INT:
return new DfIntColumnStored(this, columnName);
case FLOAT:
return new DfFloatColumnStored(this, columnName);
default:
throw exceptionByKey("DF_ADD_COL_UNKNOWN_TYPE")
.with("columnName", columnName)
Expand Down Expand Up @@ -494,6 +513,8 @@ public DfColumnComputed createComputedColumn(String columnName, ValueType type,
return new DfDecimalColumnComputed(this, columnName, expressionAsString);
case INT:
return new DfIntColumnComputed(this, columnName, expressionAsString);
case FLOAT:
return new DfFloatColumnComputed(this, columnName, expressionAsString);
default:
throw exceptionByKey("DF_ADD_COL_UNKNOWN_TYPE").with("columnName", columnName)
.with("type", type)
Expand Down Expand Up @@ -615,6 +636,11 @@ public DfDoubleColumn getDoubleColumn(String columnName)
return (DfDoubleColumn) this.getColumnNamed(columnName);
}

public DfFloatColumn getFloatColumn(String columnName)
{
return (DfFloatColumn) this.getColumnNamed(columnName);
}

public DfDateColumn getDateColumn(String columnName)
{
return (DfDateColumn) this.getColumnNamed(columnName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package io.github.vmzakharov.ecdataframe.dataframe;

import io.github.vmzakharov.ecdataframe.dataframe.compare.DoubleComparisonResult;
import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
import org.eclipse.collections.api.list.primitive.ImmutableFloatList;
import org.eclipse.collections.impl.factory.primitive.FloatLists;
import org.eclipse.collections.impl.list.primitive.IntInterval;

abstract public class DfFloatColumn
extends DfColumnAbstract
{
public DfFloatColumn(DataFrame newDataFrame, String newName)
{
super(newDataFrame, newName);
}

abstract public float getFloat(int rowIndex);

@Override
public String getValueAsString(int rowIndex)
{
return Float.toString(this.getFloat(rowIndex));
}

public ImmutableFloatList toFloatList()
{
int rowCount = this.getDataFrame().rowCount();
if (rowCount == 0)
{
return FloatLists.immutable.empty();
}

return IntInterval
.zeroTo(rowCount - 1)
.collectFloat(this::getFloat, FloatLists.mutable.withInitialCapacity(rowCount))
.toImmutable();
}

public ValueType getType()
{
return ValueType.FLOAT;
}

@Override
public void addRowToColumn(int rowIndex, DfColumn target)
{
if (this.isNull(rowIndex))
{
target.addEmptyValue();
}
else
{
((DfFloatColumnStored) target).addFloat(this.getFloat(rowIndex));
}
}

@Override
public DfColumn mergeWithInto(DfColumn other, DataFrame target)
{
DfFloatColumn mergedCol = (DfFloatColumn) this.validateAndCreateTargetColumn(other, target);

mergedCol.addAllItemsFrom(this);
mergedCol.addAllItemsFrom((DfFloatColumn) other);

return mergedCol;
}

public DfColumn copyTo(DataFrame target)
{
DfFloatColumn targetCol = (DfFloatColumn) this.copyColumnSchemaAndEnsureCapacity(target);

targetCol.addAllItemsFrom(this);
return targetCol;
}

protected abstract void addAllItemsFrom(DfFloatColumn items);

@Override
public DfCellComparator columnComparator(DfColumn otherColumn)
{
DfFloatColumn otherFloatColumn = (DfFloatColumn) otherColumn;

return (thisRowIndex, otherRowIndex) -> {
int thisMappedIndex = this.dataFrameRowIndex(thisRowIndex);
int otherMappedIndex = otherFloatColumn.dataFrameRowIndex(otherRowIndex);

return new DoubleComparisonResult(
() -> this.getFloat(thisMappedIndex),
() -> otherFloatColumn.getFloat(otherMappedIndex),
this.isNull(thisMappedIndex),
otherFloatColumn.isNull(otherMappedIndex)
);
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package io.github.vmzakharov.ecdataframe.dataframe;

import io.github.vmzakharov.ecdataframe.dsl.Expression;
import io.github.vmzakharov.ecdataframe.dsl.value.FloatValue;
import io.github.vmzakharov.ecdataframe.dsl.value.Value;
import io.github.vmzakharov.ecdataframe.util.ExpressionParserHelper;

public class DfFloatColumnComputed
extends DfFloatColumn
implements DfColumnComputed
{
private final String expressionAsString;
private final Expression expression;

public DfFloatColumnComputed(DataFrame newDataFrame, String newName, String newExpressionAsString)
{
super(newDataFrame, newName);
this.expressionAsString = newExpressionAsString;

this.expression = ExpressionParserHelper.DEFAULT.toExpressionOrScript(this.expressionAsString);
}

@Override
public Object getObject(int rowIndex)
{
Value result = this.getValue(rowIndex);

return result.isVoid() ? null : ((FloatValue) result).floatValue();
}

@Override
public float getFloat(int rowIndex)
{
Value result = this.getValue(rowIndex);

if (result.isVoid())
{
throw new NullPointerException("Null value at " + this.getName() + "[" + rowIndex + "]");
}

return ((FloatValue) result).floatValue();
}

@Override
protected void addAllItemsFrom(DfFloatColumn floatColumn)
{
this.throwUnmodifiableColumnException();
}

@Override
public int getSize()
{
return this.getDataFrame().rowCount();
}

@Override
public String getExpressionAsString()
{
return this.expressionAsString;
}

@Override
public Expression getExpression()
{
return this.expression;
}

@Override
public boolean isNull(int rowIndex)
{
return this.getObject(rowIndex) == null;
}
}
Loading

0 comments on commit ffaf911

Please sign in to comment.