Skip to content

Commit

Permalink
Merge pull request #280 from sgomadam/stockfunctions
Browse files Browse the repository at this point in the history
New Math Stock functions - intSum, doubleSum, longSum, divide and divideAndRound
  • Loading branch information
Milo Simpson authored Oct 25, 2016
2 parents e7929cd + 183977b commit 7ba1836
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 21 deletions.
4 changes: 3 additions & 1 deletion jolt-core/src/main/java/com/bazaarvoice/jolt/Modifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ public abstract class Modifier implements SpecDriven, ContextualTransform {
STOCK_FUNCTIONS.put( "intSum", new Math.intSum() );
STOCK_FUNCTIONS.put( "doubleSum", new Math.doubleSum() );
STOCK_FUNCTIONS.put( "longSum", new Math.longSum() );
STOCK_FUNCTIONS.put( "div", new Math.div() );
STOCK_FUNCTIONS.put( "divide", new Math.divide() );
STOCK_FUNCTIONS.put( "divideAndRound", new Math.divideAndRound() );


STOCK_FUNCTIONS.put( "toInteger", new Objects.toInteger() );
STOCK_FUNCTIONS.put( "toDouble", new Objects.toDouble() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

import com.bazaarvoice.jolt.common.Optional;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.List;

@SuppressWarnings( "deprecated" )
Expand Down Expand Up @@ -237,7 +240,7 @@ public static Optional<Long> longSum(List<Object> args) {
return Optional.of(sum);
}

public static Optional<Double> div(List<Object> argList) {
public static Optional<Double> divide(List<Object> argList) {

if(argList.size() < 2) {
return Optional.empty();
Expand All @@ -261,6 +264,19 @@ public static Optional<Double> div(List<Object> argList) {
return Optional.empty();
}

public static Optional<Double> divideAndRound(List<Object> argList, int digitsAfterDecimalPoint ) {

Optional<Double> divideResult = divide(argList);

if(divideResult.isPresent()){
Double divResult = divideResult.get();
BigDecimal bigDecimal = new BigDecimal(divResult).setScale(digitsAfterDecimalPoint, RoundingMode.HALF_UP);
return Optional.of(bigDecimal.doubleValue());
}

return Optional.empty();
}

@SuppressWarnings( "unchecked" )
public static final class max extends Function.BaseFunction<Object> {
@Override
Expand Down Expand Up @@ -307,14 +323,25 @@ protected Optional<Number> applySingle( final Object arg ) {
}

@SuppressWarnings( "unchecked" )
public static final class div extends Function.ListFunction {
public static final class divide extends Function.ListFunction {

@Override
protected Optional<Object> applyList(List<Object> argList) {
return (Optional)div(argList);
return (Optional)divide(argList);
}

}

@SuppressWarnings( "unchecked" )
public static final class divideAndRound extends Function.ArgDrivenListFunction<Integer> {


@Override
protected Optional<Object> applyList(Integer digitsAfterDecimalPoint, List<Object> args) {
return (Optional)divideAndRound(args, digitsAfterDecimalPoint);
}
}

@SuppressWarnings( "unchecked" )
public static final class avg extends Function.ListFunction {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public Iterator<Object[]> getTestCases() {
Function DOUBLE_SUM_OF = new Math.doubleSum();
Function LONG_SUM_OF = new Math.longSum();

Function DIV_OF = new Math.div();
Function DIV_OF = new Math.divide();
Function DIV_AND_ROUND_OF = new Math.divideAndRound();

testCases.add( new Object[] { "max-empty-array", MAX_OF, new Object[] {}, Optional.empty() } );
testCases.add( new Object[] { "max-empty-list", MAX_OF, new ArrayList( ), Optional.empty() } );
Expand Down Expand Up @@ -134,7 +135,6 @@ public Iterator<Object[]> getTestCases() {
testCases.add( new Object[] { "min-NaN-positive-infinity", MIN_OF, Arrays.asList( -1.0, Double.NaN, Double.NEGATIVE_INFINITY ), Optional.of( Double.NaN ) } );



testCases.add( new Object[] { "abs-null", ABS_OF, null, Optional.empty() } );
testCases.add( new Object[] { "abs-invalid", ABS_OF, new Object(), Optional.empty() } );
testCases.add( new Object[] { "abs-empty-list", ABS_OF, new Object[] {}, Optional.empty() } );
Expand All @@ -155,7 +155,6 @@ public Iterator<Object[]> getTestCases() {
testCases.add( new Object[] { "abs-NefInfinity", ABS_OF, Double.NEGATIVE_INFINITY, Optional.of(Double.POSITIVE_INFINITY) } );



testCases.add( new Object[] { "toInt-null", TO_INTEGER, null, Optional.empty() } );
testCases.add( new Object[] { "toInt-invalid", TO_INTEGER, new Object(), Optional.empty() } );
testCases.add( new Object[] { "toInt-empty-array", TO_INTEGER, new Object[] {}, Optional.empty() } );
Expand All @@ -180,7 +179,6 @@ public Iterator<Object[]> getTestCases() {
testCases.add( new Object[] { "toInt-single-negative-double-array", TO_INTEGER, Arrays.asList( -1.0, -2.0 ), Optional.of( Arrays.asList( -1, -2 ) ) } );



testCases.add( new Object[] { "toDouble-null", TO_DOUBLE, null, Optional.empty() } );
testCases.add( new Object[] { "toDouble-invalid", TO_DOUBLE, new Object(), Optional.empty() } );
testCases.add( new Object[] { "toDouble-empty-array", TO_DOUBLE, new Object[] {}, Optional.empty() } );
Expand All @@ -205,7 +203,6 @@ public Iterator<Object[]> getTestCases() {
testCases.add( new Object[] { "toDouble-single-negative-double-array", TO_DOUBLE, Arrays.asList( -1.0, -2.0 ), Optional.of( Arrays.asList( -1.0, -2.0 ) ) } );



testCases.add( new Object[] { "toLong-null", TO_LONG, null, Optional.empty() } );
testCases.add( new Object[] { "toLong-invalid", TO_LONG, new Object(), Optional.empty() } );
testCases.add( new Object[] { "toLong-empty-array", TO_LONG, new Object[] {}, Optional.empty() } );
Expand All @@ -229,8 +226,6 @@ public Iterator<Object[]> getTestCases() {
testCases.add( new Object[] { "toLong-single-positive-double-list", TO_LONG, new Object[] {1L, 2L}, Optional.of( Arrays.asList( 1L, 2L ) ) } );
testCases.add( new Object[] { "toLong-single-negative-double-array", TO_LONG, Arrays.asList( -1L, -2L ), Optional.of( Arrays.asList( -1L, -2L ) ) } );



testCases.add( new Object[] { "toInteger-combo-string-array", TO_INTEGER, Arrays.asList( "-1", 2, -3L, 4.0 ), Optional.of( Arrays.asList( -1, 2, -3, 4 ) ) } );
testCases.add( new Object[] { "toLong-combo-int-array", TO_LONG, Arrays.asList( "-1", 2, -3L, 4.0 ), Optional.of( Arrays.asList( -1L, 2L, -3L, 4L ) ) } );
testCases.add( new Object[] { "toDouble-combo-long-array", TO_DOUBLE, Arrays.asList( "-1", 2, -3L, 4.0 ), Optional.of( Arrays.asList( -1.0, 2.0, -3.0, 4.0 ) ) } );
Expand Down Expand Up @@ -259,6 +254,11 @@ public Iterator<Object[]> getTestCases() {
// Dividing 0 by any number returns 0.0(double)
testCases.add( new Object[] { "div-combo-valid-array", DIV_OF, Arrays.asList(0.0, 10, 2), Optional.of(0.0)});

testCases.add( new Object[] { "divAndRound-single-precision-array", DIV_AND_ROUND_OF, Arrays.asList(1, 5.0, 2), Optional.of(2.5)});
testCases.add( new Object[] { "divAndRound-double-precision-array", DIV_AND_ROUND_OF, Arrays.asList(2, 5.0, 2), Optional.of(2.50)});
testCases.add( new Object[] { "divAndRound-trailing-precision-array", DIV_AND_ROUND_OF, Arrays.asList(3, 5.0, 2), Optional.of(2.500)});
testCases.add( new Object[] { "divAndRound-no-precision-array", DIV_AND_ROUND_OF, Arrays.asList(0, 5.0, 2), Optional.of(3.0)}); // Round up as >= 0.5
testCases.add( new Object[] { "divAndRound-no-precision-array", DIV_AND_ROUND_OF, Arrays.asList(0, 4.8, 2), Optional.of(2.0)}); // Round down as < 0.5

return testCases.iterator();
}
Expand Down
22 changes: 12 additions & 10 deletions jolt-core/src/test/resources/json/modifier/functions/mathTests.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"test1": [5, 2.0], // Divide integer and double returns double
"test2": [5, 0], // Divide by 0 returns empty hence noop
"test3": [0, 5], // Divide 0 by any number returns 0
"nr": 10,
"dr": 5
"nr": 51,
"dr": 13
}
},

Expand Down Expand Up @@ -46,11 +46,12 @@
"value": "=intSum"
},
"data4": {
"test1": "=div",
"test2": "=div",
"test3": "=div",
"explicit": "=div(@(1,value))",
"div": "=div(@(1,nr),@(1,dr))" // Look up the numerator and denominator from the input
"test1": "=divide",
"test2": "=divide",
"test3": "=divide",
"explicit": "=divide(@(1,value))",
"div": "=divide(@(1,nr),@(1,dr))" , // Look up the numerator and denominator from the input
"roundedDiv": "=divideAndRound(4, @(1,nr),@(1,dr))" // Round the result to the 4 decimal points
}
},

Expand Down Expand Up @@ -88,11 +89,12 @@
"test1": 2.5,
"test2": [5, 0],
"test3": 0.0,
"div": 2.0,
"div": 3.923076923076923,
"roundedDiv":3.9231,
"explicit": 2.5,
"value": [5, 2],
"nr": 10,
"dr": 5
"nr": 51,
"dr": 13
}
}
}

0 comments on commit 7ba1836

Please sign in to comment.