public static void inputLongDecimal(Type type, LongDecimalWithOverflowState state, Block block, int position) { accumulateValueInState(type.getSlice(block, position), state); }
@Override public InternalAggregationFunction specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type inputType = typeManager.getType(getOnlyElement(applyBoundVariables(getSignature().getArgumentTypes(), boundVariables))); Type outputType = typeManager.getType(applyBoundVariables(getSignature().getReturnType(), boundVariables)); return generateAggregation(inputType, outputType); }
@Test public void testCombineUnderflow() { addToState(state, TWO.pow(125).negate()); addToState(state, TWO.pow(126).negate()); LongDecimalWithOverflowState otherState = new LongDecimalWithOverflowStateFactory().createSingleState(); addToState(otherState, TWO.pow(125).negate()); addToState(otherState, TWO.pow(126).negate()); DecimalSumAggregation.combine(state, otherState); assertEquals(state.getOverflow(), -1); assertEquals(state.getLongDecimal(), unscaledDecimal(TWO.pow(126).negate())); }
private static void addToState(LongDecimalWithOverflowState state, BigInteger value) { BlockBuilder blockBuilder = TYPE.createFixedSizeBlockBuilder(1); TYPE.writeSlice(blockBuilder, unscaledDecimal(value)); DecimalSumAggregation.inputLongDecimal(TYPE, state, blockBuilder.build(), 0); } }
@Test(expectedExceptions = ArithmeticException.class) public void testOverflowOnOutput() { addToState(state, TWO.pow(126)); addToState(state, TWO.pow(126)); assertEquals(state.getOverflow(), 1); DecimalSumAggregation.outputLongDecimal(TYPE, state, new VariableWidthBlockBuilder(null, 10, 100)); }
private static void accumulateValueInState(Slice unscaledDecimal, LongDecimalWithOverflowState state) { initializeIfNeeded(state); Slice sum = state.getLongDecimal(); long overflow = UnscaledDecimal128Arithmetic.addWithOverflow(sum, unscaledDecimal, sum); state.setOverflow(state.getOverflow() + overflow); }
private static InternalAggregationFunction generateAggregation(Type inputType, Type outputType) { checkArgument(inputType instanceof DecimalType, "type must be Decimal"); DynamicClassLoader classLoader = new DynamicClassLoader(DecimalSumAggregation.class.getClassLoader()); List<Type> inputTypes = ImmutableList.of(inputType); MethodHandle inputFunction; Class<? extends AccumulatorState> stateInterface = LongDecimalWithOverflowState.class; AccumulatorStateSerializer<?> stateSerializer = new LongDecimalWithOverflowStateSerializer(); if (((DecimalType) inputType).isShort()) { inputFunction = SHORT_DECIMAL_INPUT_FUNCTION; } else { inputFunction = LONG_DECIMAL_INPUT_FUNCTION; } AggregationMetadata metadata = new AggregationMetadata( generateAggregationName(NAME, outputType.getTypeSignature(), inputTypes.stream().map(Type::getTypeSignature).collect(toImmutableList())), createInputParameterMetadata(inputType), inputFunction.bindTo(inputType), COMBINE_FUNCTION, LONG_DECIMAL_OUTPUT_FUNCTION.bindTo(outputType), ImmutableList.of(new AccumulatorStateDescriptor( stateInterface, stateSerializer, new LongDecimalWithOverflowStateFactory())), outputType); Type intermediateType = stateSerializer.getSerializedType(); GenericAccumulatorFactoryBinder factory = AccumulatorCompiler.generateAccumulatorFactoryBinder(metadata, classLoader); return new InternalAggregationFunction(NAME, inputTypes, ImmutableList.of(intermediateType), outputType, true, false, factory); }
@Test public void testCombineUnderflow() { addToState(state, TWO.pow(125).negate()); addToState(state, TWO.pow(126).negate()); LongDecimalWithOverflowState otherState = new LongDecimalWithOverflowStateFactory().createSingleState(); addToState(otherState, TWO.pow(125).negate()); addToState(otherState, TWO.pow(126).negate()); DecimalSumAggregation.combine(state, otherState); assertEquals(state.getOverflow(), -1); assertEquals(state.getLongDecimal(), unscaledDecimal(TWO.pow(126).negate())); }
private static void addToState(LongDecimalWithOverflowState state, BigInteger value) { BlockBuilder blockBuilder = TYPE.createFixedSizeBlockBuilder(1); TYPE.writeSlice(blockBuilder, unscaledDecimal(value)); DecimalSumAggregation.inputLongDecimal(TYPE, state, blockBuilder.build(), 0); } }
@Test(expectedExceptions = ArithmeticException.class) public void testOverflowOnOutput() { addToState(state, TWO.pow(126)); addToState(state, TWO.pow(126)); assertEquals(state.getOverflow(), 1); DecimalSumAggregation.outputLongDecimal(TYPE, state, new VariableWidthBlockBuilder(null, 10, 100)); }
private static void accumulateValueInState(Slice unscaledDecimal, LongDecimalWithOverflowState state) { initializeIfNeeded(state); Slice sum = state.getLongDecimal(); long overflow = UnscaledDecimal128Arithmetic.addWithOverflow(sum, unscaledDecimal, sum); state.setOverflow(state.getOverflow() + overflow); }
private static InternalAggregationFunction generateAggregation(Type inputType, Type outputType) { checkArgument(inputType instanceof DecimalType, "type must be Decimal"); DynamicClassLoader classLoader = new DynamicClassLoader(DecimalSumAggregation.class.getClassLoader()); List<Type> inputTypes = ImmutableList.of(inputType); MethodHandle inputFunction; Class<? extends AccumulatorState> stateInterface = LongDecimalWithOverflowState.class; AccumulatorStateSerializer<?> stateSerializer = new LongDecimalWithOverflowStateSerializer(); if (((DecimalType) inputType).isShort()) { inputFunction = SHORT_DECIMAL_INPUT_FUNCTION; } else { inputFunction = LONG_DECIMAL_INPUT_FUNCTION; } AggregationMetadata metadata = new AggregationMetadata( generateAggregationName(NAME, outputType.getTypeSignature(), inputTypes.stream().map(Type::getTypeSignature).collect(toImmutableList())), createInputParameterMetadata(inputType), inputFunction.bindTo(inputType), COMBINE_FUNCTION, LONG_DECIMAL_OUTPUT_FUNCTION.bindTo(outputType), ImmutableList.of(new AccumulatorStateDescriptor( stateInterface, stateSerializer, new LongDecimalWithOverflowStateFactory())), outputType); Type intermediateType = stateSerializer.getSerializedType(); GenericAccumulatorFactoryBinder factory = AccumulatorCompiler.generateAccumulatorFactoryBinder(metadata, classLoader); return new InternalAggregationFunction(NAME, inputTypes, ImmutableList.of(intermediateType), outputType, true, false, factory); }
@Override public InternalAggregationFunction specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type inputType = typeManager.getType(getOnlyElement(applyBoundVariables(getSignature().getArgumentTypes(), boundVariables))); Type outputType = typeManager.getType(applyBoundVariables(getSignature().getReturnType(), boundVariables)); return generateAggregation(inputType, outputType); }
public static void inputLongDecimal(Type type, LongDecimalWithOverflowState state, Block block, int position) { accumulateValueInState(type.getSlice(block, position), state); }
@Test public void testCombineOverflow() { addToState(state, TWO.pow(125)); addToState(state, TWO.pow(126)); LongDecimalWithOverflowState otherState = new LongDecimalWithOverflowStateFactory().createSingleState(); addToState(otherState, TWO.pow(125)); addToState(otherState, TWO.pow(126)); DecimalSumAggregation.combine(state, otherState); assertEquals(state.getOverflow(), 1); assertEquals(state.getLongDecimal(), unscaledDecimal(TWO.pow(126))); }
public static void inputShortDecimal(Type type, LongDecimalWithOverflowState state, Block block, int position) { accumulateValueInState(unscaledDecimal(type.getLong(block, position)), state); }
@Test public void testCombineOverflow() { addToState(state, TWO.pow(125)); addToState(state, TWO.pow(126)); LongDecimalWithOverflowState otherState = new LongDecimalWithOverflowStateFactory().createSingleState(); addToState(otherState, TWO.pow(125)); addToState(otherState, TWO.pow(126)); DecimalSumAggregation.combine(state, otherState); assertEquals(state.getOverflow(), 1); assertEquals(state.getLongDecimal(), unscaledDecimal(TWO.pow(126))); }
public static void inputShortDecimal(Type type, LongDecimalWithOverflowState state, Block block, int position) { accumulateValueInState(unscaledDecimal(type.getLong(block, position)), state); }
public static void combine(LongDecimalWithOverflowState state, LongDecimalWithOverflowState otherState) { state.setOverflow(state.getOverflow() + otherState.getOverflow()); if (state.getLongDecimal() == null) { state.setLongDecimal(otherState.getLongDecimal()); } else { accumulateValueInState(otherState.getLongDecimal(), state); } }
public static void combine(LongDecimalWithOverflowState state, LongDecimalWithOverflowState otherState) { state.setOverflow(state.getOverflow() + otherState.getOverflow()); if (state.getLongDecimal() == null) { state.setLongDecimal(otherState.getLongDecimal()); } else { accumulateValueInState(otherState.getLongDecimal(), state); } }