You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pig.apache.org by ch...@apache.org on 2014/05/11 00:59:53 UTC

svn commit: r1593742 - in /pig/trunk: src/org/apache/pig/builtin/DoubleRoundTo.java src/org/apache/pig/builtin/FloatRoundTo.java src/org/apache/pig/builtin/ROUND_TO.java test/org/apache/pig/test/TestBuiltin.java

Author: cheolsoo
Date: Sat May 10 22:59:52 2014
New Revision: 1593742

URL: http://svn.apache.org/r1593742
Log:
PIG-3926: ROUND_TO function: rounds double/float to fixed number of decimal
places - addendum patch (mrflip via cheolsoo)

Modified:
    pig/trunk/src/org/apache/pig/builtin/DoubleRoundTo.java
    pig/trunk/src/org/apache/pig/builtin/FloatRoundTo.java
    pig/trunk/src/org/apache/pig/builtin/ROUND_TO.java
    pig/trunk/test/org/apache/pig/test/TestBuiltin.java

Modified: pig/trunk/src/org/apache/pig/builtin/DoubleRoundTo.java
URL: http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/builtin/DoubleRoundTo.java?rev=1593742&r1=1593741&r2=1593742&view=diff
==============================================================================
--- pig/trunk/src/org/apache/pig/builtin/DoubleRoundTo.java (original)
+++ pig/trunk/src/org/apache/pig/builtin/DoubleRoundTo.java Sat May 10 22:59:52 2014
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.ArrayList;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 
 import org.apache.pig.EvalFunc;
 import org.apache.pig.FuncSpec;
@@ -36,15 +37,22 @@ import org.apache.pig.impl.logicalLayer.
  * BigDecimal. The too-often seen trick of doing (1000.0 * ROUND(x/1000)) is not
  * only hard to read but also fails to produce numerically accurate results.
  *
- * Given a single data atom and precision it Returns a double extending to the
- * given number of decimal places. ROUND_TO(0.9876543, 3) is 0.988;
- * ROUND_TO(0.9876543, 0) is 1.0.
+ * Given a single data atom and number of digits, it returns a double extending to the
+ * given number of decimal places.
+ *
+ * The result is a multiple of ten to the power given by the digits argument: a
+ * negative value zeros out correspondingly many places to the left of the
+ * decimal point: ROUND_TO(0.9876543, 3) is 0.988; ROUND_TO(0.9876543, 0) is
+ * 1.0; and ROUND_TO(1234.56, -2) is 1200.0.
+ *
+ * The optional mode argument specifies the {@link java.math.RoundingMode rounding mode};
+ * by default, {@link java.math.RoundingMode#HALF_EVEN 'HALF_EVEN'} is used.
  *
  */
 public class DoubleRoundTo extends EvalFunc<Double>{
     /**
      * java level API
-     * @param input expects a numeric value to round and a number of digits to keep
+     * @param input expects a numeric value to round, a number of digits to keep, and an optional rounding mode.
      * @return output returns a single numeric value, the number with only those digits retained
      */
     @Override
@@ -53,11 +61,14 @@ public class DoubleRoundTo extends EvalF
             return null;
 
         try {
-            Double     num    = (Double)input.get(0);
-            Integer    digits = (Integer)input.get(1);
-            BigDecimal bdnum  = BigDecimal.valueOf(num);
+            Double       num    = (Double)input.get(0);
+            Integer      digits = (Integer)input.get(1);
+            RoundingMode mode   = (input.size() >= 3) ?
+                RoundingMode.valueOf(DataType.toInteger(input.get(2))) : RoundingMode.HALF_EVEN;
+            if (num == null) return null;
 
-            bdnum = bdnum.setScale(digits, BigDecimal.ROUND_HALF_UP);
+            BigDecimal bdnum  = BigDecimal.valueOf(num);
+            bdnum = bdnum.setScale(digits, mode);
             return bdnum.doubleValue();
         } catch (Exception e){
             throw new IOException("Caught exception processing input row ", e);
@@ -71,11 +82,17 @@ public class DoubleRoundTo extends EvalF
     public List<FuncSpec> getArgToFuncMapping() throws FrontendException {
         List<FuncSpec> funcList = new ArrayList<FuncSpec>();
 
-        Schema s_dbl = new Schema();
-        s_dbl.add(new Schema.FieldSchema(null, DataType.DOUBLE));
-        s_dbl.add(new Schema.FieldSchema(null, DataType.INTEGER));
+        Schema s_dbl_2 = new Schema();
+        s_dbl_2.add(new Schema.FieldSchema(null, DataType.DOUBLE));
+        s_dbl_2.add(new Schema.FieldSchema(null, DataType.INTEGER));
+
+        Schema s_dbl_3 = new Schema();
+        s_dbl_3.add(new Schema.FieldSchema(null, DataType.DOUBLE));
+        s_dbl_3.add(new Schema.FieldSchema(null, DataType.INTEGER));
+        s_dbl_3.add(new Schema.FieldSchema(null, DataType.INTEGER));
 
-        funcList.add(new FuncSpec(this.getClass().getName(), s_dbl));
+        funcList.add(new FuncSpec(this.getClass().getName(), s_dbl_2));
+        funcList.add(new FuncSpec(this.getClass().getName(), s_dbl_3));
 
         return funcList;
     }

Modified: pig/trunk/src/org/apache/pig/builtin/FloatRoundTo.java
URL: http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/builtin/FloatRoundTo.java?rev=1593742&r1=1593741&r2=1593742&view=diff
==============================================================================
--- pig/trunk/src/org/apache/pig/builtin/FloatRoundTo.java (original)
+++ pig/trunk/src/org/apache/pig/builtin/FloatRoundTo.java Sat May 10 22:59:52 2014
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.ArrayList;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 
 import org.apache.pig.EvalFunc;
 import org.apache.pig.FuncSpec;
@@ -36,15 +37,22 @@ import org.apache.pig.impl.logicalLayer.
  * BigDecimal. The too-often seen trick of doing (1000.0 * ROUND(x/1000)) is not
  * only hard to read but also fails to produce numerically accurate results.
  *
- * Given a single data atom and precision it Returns a float extending to the
- * given number of decimal places. ROUND_TO(0.9876543, 3) is 0.988;
- * ROUND_TO(0.9876543, 0) is 1.0.
+ * Given a single data atom and number of digits, it returns a float extending to the
+ * given number of decimal places.
+ *
+ * The result is a multiple of ten to the power given by the digits argument: a
+ * negative value zeros out correspondingly many places to the left of the
+ * decimal point: ROUND_TO(0.9876543, 3) is 0.988; ROUND_TO(0.9876543, 0) is
+ * 1.0; and ROUND_TO(1234.56, -2) is 1200.0.
+ *
+ * The optional mode argument specifies the {@link java.math.RoundingMode rounding mode};
+ * by default, {@link java.math.RoundingMode#HALF_EVEN HALF_EVEN} is used.
  *
  */
 public class FloatRoundTo extends EvalFunc<Float>{
     /**
      * java level API
-     * @param input expects a numeric value to round and a number of digits to keep
+     * @param input expects a numeric value to round, a number of digits to keep, and an optional rounding mode.
      * @return output returns a single numeric value, the number with only those digits retained
      */
     @Override
@@ -53,16 +61,19 @@ public class FloatRoundTo extends EvalFu
             return null;
 
         try {
-            Float      num    = (Float)input.get(0);
-            Integer    digits = (Integer)input.get(1);
-            BigDecimal bdnum  = BigDecimal.valueOf(num);
+            Float        num    = (Float)input.get(0);
+            Integer      digits = (Integer)input.get(1);
+            RoundingMode mode   = (input.size() >= 3) ?
+                RoundingMode.valueOf(DataType.toInteger(input.get(2))) : RoundingMode.HALF_EVEN;
+            if (num == null) return null;
 
-            bdnum = bdnum.setScale(digits, BigDecimal.ROUND_HALF_UP);
+            BigDecimal bdnum  = BigDecimal.valueOf(num);
+            bdnum = bdnum.setScale(digits, mode);
             return bdnum.floatValue();
         } catch (Exception e){
             throw new IOException("Caught exception processing input row ", e);
         }
-	}
+    }
 
     /* (non-Javadoc)
      * @see org.apache.pig.EvalFunc#getArgToFuncMapping()
@@ -71,11 +82,17 @@ public class FloatRoundTo extends EvalFu
     public List<FuncSpec> getArgToFuncMapping() throws FrontendException {
         List<FuncSpec> funcList = new ArrayList<FuncSpec>();
 
-        Schema s_flt = new Schema();
-        s_flt.add(new Schema.FieldSchema(null, DataType.FLOAT));
-        s_flt.add(new Schema.FieldSchema(null, DataType.INTEGER));
+        Schema s_flt_2 = new Schema();
+        s_flt_2.add(new Schema.FieldSchema(null, DataType.FLOAT));
+        s_flt_2.add(new Schema.FieldSchema(null, DataType.INTEGER));
+
+        Schema s_flt_3 = new Schema();
+        s_flt_3.add(new Schema.FieldSchema(null, DataType.FLOAT));
+        s_flt_3.add(new Schema.FieldSchema(null, DataType.INTEGER));
+        s_flt_3.add(new Schema.FieldSchema(null, DataType.INTEGER));
 
-        funcList.add(new FuncSpec(this.getClass().getName(), s_flt));
+        funcList.add(new FuncSpec(this.getClass().getName(), s_flt_2));
+        funcList.add(new FuncSpec(this.getClass().getName(), s_flt_3));
 
         return funcList;
     }

Modified: pig/trunk/src/org/apache/pig/builtin/ROUND_TO.java
URL: http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/builtin/ROUND_TO.java?rev=1593742&r1=1593741&r2=1593742&view=diff
==============================================================================
--- pig/trunk/src/org/apache/pig/builtin/ROUND_TO.java (original)
+++ pig/trunk/src/org/apache/pig/builtin/ROUND_TO.java Sat May 10 22:59:52 2014
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.ArrayList;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 
 import org.apache.pig.EvalFunc;
 import org.apache.pig.FuncSpec;
@@ -37,15 +38,22 @@ import org.apache.pig.impl.logicalLayer.
  * BigDecimal. The too-often seen trick of doing (1000.0 * ROUND(x/1000)) is not
  * only hard to read but also fails to produce numerically accurate results.
  *
- * Given a single data atom and precision it Returns a double extending to the
- * given number of decimal places. ROUND_TO(0.9876543, 3) is 0.988;
- * ROUND_TO(0.9876543, 0) is 1.0.
+ * Given a single data atom and number of digits, it returns a double extending to the
+ * given number of decimal places.
+ *
+ * The result is a multiple of ten to the power given by the digits argument: a
+ * negative value zeros out correspondingly many places to the left of the
+ * decimal point: ROUND_TO(0.9876543, 3) is 0.988; ROUND_TO(0.9876543, 0) is
+ * 1.0; and ROUND_TO(1234.56, -2) is 1200.0.
+ *
+ * The optional mode argument specifies the {@link java.math.RoundingMode rounding mode};
+ * by default, {@link java.math.RoundingMode#HALF_EVEN HALF_EVEN} is used.
  *
  */
 public class ROUND_TO extends EvalFunc<Double>{
     /**
      * java level API
-     * @param input expects a numeric value to round and a number of digits to keep
+     * @param input expects a numeric value to round, a number of digits to keep, and an optional rounding mode.
      * @return output returns a single numeric value, the number with only those digits retained
      */
     @Override
@@ -54,11 +62,14 @@ public class ROUND_TO extends EvalFunc<D
             return null;
 
         try {
-            Double     num    = DataType.toDouble(input.get(0));
-            Integer    digits = DataType.toInteger(input.get(1));
-            BigDecimal bdnum  = BigDecimal.valueOf(num);
+            Double       num    = DataType.toDouble(input.get(0));
+            Integer      digits = DataType.toInteger(input.get(1));
+            RoundingMode mode   = (input.size() >= 3) ?
+                RoundingMode.valueOf(DataType.toInteger(input.get(2))) : RoundingMode.HALF_EVEN;
+            if (num == null) return null;
 
-            bdnum = bdnum.setScale(digits, BigDecimal.ROUND_HALF_UP);
+            BigDecimal bdnum  = BigDecimal.valueOf(num);
+            bdnum = bdnum.setScale(digits, mode);
             return bdnum.doubleValue();
         } catch (NumberFormatException nfe){
             System.err.println("Failed to process input; error - " + nfe.getMessage());
@@ -81,21 +92,36 @@ public class ROUND_TO extends EvalFunc<D
     public List<FuncSpec> getArgToFuncMapping() throws FrontendException {
         List<FuncSpec> funcList = new ArrayList<FuncSpec>();
 
-        Schema s_bty = new Schema();
-        s_bty.add(new Schema.FieldSchema(null, DataType.BYTEARRAY));
-        s_bty.add(new Schema.FieldSchema(null, DataType.BYTEARRAY));
-
-        Schema s_dbl = new Schema();
-        s_dbl.add(new Schema.FieldSchema(null, DataType.DOUBLE));
-        s_dbl.add(new Schema.FieldSchema(null, DataType.INTEGER));
-
-        Schema s_flt = new Schema();
-        s_flt.add(new Schema.FieldSchema(null, DataType.FLOAT));
-        s_flt.add(new Schema.FieldSchema(null, DataType.INTEGER));
-
-        funcList.add(new FuncSpec(this.getClass().getName(),     s_bty));
-        funcList.add(new FuncSpec(DoubleRoundTo.class.getName(), s_dbl));
-        funcList.add(new FuncSpec(FloatRoundTo.class.getName(),  s_flt));
+        Schema s_bty_2 = new Schema();
+        s_bty_2.add(new Schema.FieldSchema(null, DataType.BYTEARRAY));
+        s_bty_2.add(new Schema.FieldSchema(null, DataType.BYTEARRAY));
+        Schema s_bty_3 = new Schema();
+        s_bty_3.add(new Schema.FieldSchema(null, DataType.BYTEARRAY));
+        s_bty_3.add(new Schema.FieldSchema(null, DataType.BYTEARRAY));
+        s_bty_3.add(new Schema.FieldSchema(null, DataType.INTEGER));
+
+        Schema s_dbl_2 = new Schema();
+        s_dbl_2.add(new Schema.FieldSchema(null, DataType.DOUBLE));
+        s_dbl_2.add(new Schema.FieldSchema(null, DataType.INTEGER));
+        Schema s_dbl_3 = new Schema();
+        s_dbl_3.add(new Schema.FieldSchema(null, DataType.DOUBLE));
+        s_dbl_3.add(new Schema.FieldSchema(null, DataType.INTEGER));
+        s_dbl_3.add(new Schema.FieldSchema(null, DataType.INTEGER));
+
+        Schema s_flt_2 = new Schema();
+        s_flt_2.add(new Schema.FieldSchema(null, DataType.FLOAT));
+        s_flt_2.add(new Schema.FieldSchema(null, DataType.INTEGER));
+        Schema s_flt_3 = new Schema();
+        s_flt_3.add(new Schema.FieldSchema(null, DataType.FLOAT));
+        s_flt_3.add(new Schema.FieldSchema(null, DataType.INTEGER));
+        s_flt_3.add(new Schema.FieldSchema(null, DataType.INTEGER));
+
+        funcList.add(new FuncSpec(this.getClass().getName(),     s_bty_2));
+        funcList.add(new FuncSpec(this.getClass().getName(),     s_bty_3));
+        funcList.add(new FuncSpec(DoubleRoundTo.class.getName(), s_dbl_2));
+        funcList.add(new FuncSpec(DoubleRoundTo.class.getName(), s_dbl_3));
+        funcList.add(new FuncSpec(FloatRoundTo.class.getName(),  s_flt_2));
+        funcList.add(new FuncSpec(FloatRoundTo.class.getName(),  s_flt_3));
 
         return funcList;
     }

Modified: pig/trunk/test/org/apache/pig/test/TestBuiltin.java
URL: http://svn.apache.org/viewvc/pig/trunk/test/org/apache/pig/test/TestBuiltin.java?rev=1593742&r1=1593741&r2=1593742&view=diff
==============================================================================
--- pig/trunk/test/org/apache/pig/test/TestBuiltin.java (original)
+++ pig/trunk/test/org/apache/pig/test/TestBuiltin.java Sat May 10 22:59:52 2014
@@ -1708,32 +1708,88 @@ public class TestBuiltin {
         Float          flt     = 0.987654321f;
         EvalFunc<Long> rounder = new ROUND();
         Tuple          tup     = TupleFactory.getInstance().newTuple(1);
-        long           expected, output;
+        long           expected, lng_out;
 
         tup.set(0, dbl);
         expected = Math.round(dbl);
-        output   = rounder.exec(tup);
-        assertTrue(output == expected);
+        lng_out   = rounder.exec(tup);
+        assertEquals(expected, lng_out);
 
         tup.set(0, flt);
         expected = Math.round(flt);
-        output   = rounder.exec(tup);
-        assertTrue(output == expected);
+        lng_out   = rounder.exec(tup);
+        assertEquals(expected, lng_out);
+
+        tup.set(0,  4.6d); assertEquals( 5l, lng_out = rounder.exec(tup));
+        tup.set(0,  2.4d); assertEquals( 2l, lng_out = rounder.exec(tup));
+        tup.set(0,  1.0d); assertEquals( 1l, lng_out = rounder.exec(tup));
+        tup.set(0, -1.0d); assertEquals(-1l, lng_out = rounder.exec(tup));
+        tup.set(0, -2.4d); assertEquals(-2l, lng_out = rounder.exec(tup));
+        tup.set(0, -4.6d); assertEquals(-5l, lng_out = rounder.exec(tup));
+
+        // Rounds towards positive infinity: round(x) = floor(x + 0.5)
+        tup.set(0,  3.5d); assertEquals( 4l, lng_out = rounder.exec(tup));
+        tup.set(0, -3.5d); assertEquals(-3l, lng_out = rounder.exec(tup));
+        tup.set(0,  2.5d); assertEquals( 3l, lng_out = rounder.exec(tup));
+        tup.set(0, -2.5d); assertEquals(-2l, lng_out = rounder.exec(tup));
+
+        // we don't need to test null input because of SKIP_UDF_CALL_FOR_NULL behavior
     }
 
     @Test
     public void testROUND_TO() throws Exception {
-        Double           dbl     = 3.1415925000d, dbl_out;
+        Double           dbl_out;
         EvalFunc<Double> rounder = new ROUND_TO();
-        Tuple            tup     = TupleFactory.getInstance().newTuple(2);
+        Tuple            tup;
         String           expected;
 
         // Returns double given double
-        tup.set(0, dbl);
-        expected = "3.141593"; tup.set(1, 6); dbl_out = rounder.exec(tup);  assertEquals(expected, dbl_out.toString());
-        expected = "3.1416";   tup.set(1, 4); dbl_out = rounder.exec(tup);  assertEquals(expected, dbl_out.toString());
-        expected = "3.1";      tup.set(1, 1); dbl_out = rounder.exec(tup);  assertEquals(expected, dbl_out.toString());
-        expected = "3.0";      tup.set(1, 0); dbl_out = rounder.exec(tup);  assertEquals(expected, dbl_out.toString());
+        tup = TupleFactory.getInstance().newTuple(2);
+        tup.set(0,1234.1789d); tup.set(1, 8); expected = "1234.1789"; dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,1234.1789d); tup.set(1, 4); expected = "1234.1789"; dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,1234.1789d); tup.set(1, 2); expected = "1234.18";   dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,1234.1789d); tup.set(1, 1); expected = "1234.2";    dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,1234.1789d); tup.set(1, 0); expected = "1234.0";    dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,1234.1789d); tup.set(1,-1); expected = "1230.0";    dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,1234.1789d); tup.set(1,-3); expected = "1000.0";    dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,1234.1789d); tup.set(1,-4); expected = "0.0";       dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,1234.1789d); tup.set(1,-5); expected = "0.0";       dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+
+        // default rounding mode is round-half-to-even
+        tup.set(0,   3.25000001d); tup.set(1, 1); expected =  "3.3";  dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,   3.25d);   tup.set(1, 1); expected =  "3.2";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -3.25d);   tup.set(1, 1); expected = "-3.2";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,   3.15d);   tup.set(1, 1); expected =  "3.2";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -3.15d);   tup.set(1, 1); expected = "-3.2";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,   3.5d);    tup.set(1, 0); expected =  "4.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -3.5d);    tup.set(1, 0); expected = "-4.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,   2.5d);    tup.set(1, 0); expected =  "2.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -2.5d);    tup.set(1, 0); expected = "-2.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+
+        // Returns double given double; rounding mode is round-half-to-even (but explicitly now)
+        tup = TupleFactory.getInstance().newTuple(3);
+        tup.set(2, 6); // java.math.RoundingMode.HALF_EVEN
+        tup.set(0,   3.25d);   tup.set(1, 1); expected =  "3.2";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -3.25d);   tup.set(1, 1); expected = "-3.2";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,   3.15d);   tup.set(1, 1); expected =  "3.2";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -3.15d);   tup.set(1, 1); expected = "-3.2";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,   3.5d);    tup.set(1, 0); expected =  "4.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -3.5d);    tup.set(1, 0); expected = "-4.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,   2.5d);    tup.set(1, 0); expected =  "2.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -2.5d);    tup.set(1, 0); expected = "-2.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+
+        // Returns double given double; rounding mode is round-half-away-from-zero
+        tup = TupleFactory.getInstance().newTuple(3);
+        tup.set(2, 4); // java.math.RoundingMode.HALF_UP
+        tup.set(0,   3.25000001d); tup.set(1, 1); expected =  "3.3";  dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,   3.25d);   tup.set(1, 1); expected =  "3.3";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -3.25d);   tup.set(1, 1); expected = "-3.3";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,   3.15d);   tup.set(1, 1); expected =  "3.2";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -3.15d);   tup.set(1, 1); expected = "-3.2";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,   3.5d);    tup.set(1, 0); expected =  "4.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -3.5d);    tup.set(1, 0); expected = "-4.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,   2.5d);    tup.set(1, 0); expected =  "3.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
+        tup.set(0,  -2.5d);    tup.set(1, 0); expected = "-3.0";      dbl_out = rounder.exec(tup); assertEquals(expected, dbl_out.toString());
     }
 
     @Test