You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by eh...@apache.org on 2014/02/01 00:27:54 UTC

svn commit: r1563338 - /hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestDecimal128.java

Author: ehans
Date: Fri Jan 31 23:27:53 2014
New Revision: 1563338

URL: http://svn.apache.org/r1563338
Log:
HIVE-6257: Add more unit tests for high-precision Decimal128 arithmetic (Eric Hanson, reviewed by Jitendra Pandey)

Modified:
    hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestDecimal128.java

Modified: hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestDecimal128.java
URL: http://svn.apache.org/viewvc/hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestDecimal128.java?rev=1563338&r1=1563337&r2=1563338&view=diff
==============================================================================
--- hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestDecimal128.java (original)
+++ hive/trunk/common/src/test/org/apache/hadoop/hive/common/type/TestDecimal128.java Fri Jan 31 23:27:53 2014
@@ -17,6 +17,9 @@ package org.apache.hadoop.hive.common.ty
 
 import static org.junit.Assert.*;
 
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
 import java.util.Random;
 
 import org.junit.After;
@@ -376,6 +379,203 @@ public class TestDecimal128 {
     verifyMultiplyDivideInverse(a, b);
   }
 
+  // Test a set of random adds at high precision.
+  @Test
+  public void testHighPrecisionDecimal128Add() {
+    final int N = 10000;
+    for (int i = 0; i < N; i++) {
+      verifyHighPrecisionAddSingle();
+    }
+  }
+
+  // Test one random hi-precision decimal add.
+  private void verifyHighPrecisionAddSingle() {
+
+    Decimal128 a, b, r;
+    String sA, sB;
+
+    a = new Decimal128();
+    sA = makeNumericString(37);
+    a.update(sA, (short) 0);
+    b = new Decimal128();
+    sB = makeNumericString(37);
+    b.update(sB, (short) 0);
+
+    r = new Decimal128();
+    r.addDestructive(a, (short) 0);
+    r.addDestructive(b, (short) 0);
+
+    String res1 = r.toFormalString();
+
+    // Now do the add with Java BigDecimal
+    BigDecimal bdA = new BigDecimal(sA);
+    BigDecimal bdB = new BigDecimal(sB);
+    BigDecimal bdR = bdA.add(bdB);
+
+    String res2 = bdR.toPlainString();
+
+    // Compare the results
+    assertEquals(res1, res2);
+  }
+
+  // Test a set of random subtracts at high precision.
+  @Test
+  public void testHighPrecisionDecimal128Subtract() {
+    final int N = 10000;
+    for (int i = 0; i < N; i++) {
+      verifyHighPrecisionSubtractSingle();
+    }
+  }
+
+  // Test one random high-precision subtract.
+  private void verifyHighPrecisionSubtractSingle() {
+
+    Decimal128 a, b, r;
+    String sA, sB;
+
+    a = new Decimal128();
+    sA = makeNumericString(37);
+    a.update(sA, (short) 0);
+    b = new Decimal128();
+    sB = makeNumericString(37);
+    b.update(sB, (short) 0);
+
+    r = new Decimal128();
+    r.addDestructive(a, (short) 0);
+    r.subtractDestructive(b, (short) 0);
+
+    String res1 = r.toFormalString();
+
+    // Now do the add with Java BigDecimal
+    BigDecimal bdA = new BigDecimal(sA);
+    BigDecimal bdB = new BigDecimal(sB);
+    BigDecimal bdR = bdA.subtract(bdB);
+
+    String res2 = bdR.toPlainString();
+
+    // Compare the results
+    assertEquals(res1, res2);
+  }
+
+  // Test a set of random multiplications at high precision.
+  @Test
+  public void testHighPrecisionDecimal128Multiply() {
+    final int N = 10000;
+    for (int i = 0; i < N; i++) {
+      verifyHighPrecisionMultiplySingle();
+    }
+  }
+
+  // Test a single, high-precision multiply of random inputs.
+  private void verifyHighPrecisionMultiplySingle() {
+
+    Decimal128 a, b, r;
+    String sA, sB;
+
+    Random rand = new Random();
+    int aDigits = rand.nextInt(37) + 1; // number of digits in a (1..37)
+    int bDigits = 38 - aDigits;         // number of digits in b (1..37)
+    assertTrue(aDigits + bDigits == 38 && aDigits > 0 && bDigits > 0);
+
+    a = new Decimal128();
+    sA = makeNumericString(aDigits);
+    a.update(sA, (short) 0);
+    b = new Decimal128();
+    sB = makeNumericString(bDigits);
+    b.update(sB, (short) 0);
+
+    r = new Decimal128();
+    r.addDestructive(a, (short) 0);
+    r.multiplyDestructive(b, (short) 0);
+
+    String res1 = r.toFormalString();
+
+    // Now do the add with Java BigDecimal
+    BigDecimal bdA = new BigDecimal(sA);
+    BigDecimal bdB = new BigDecimal(sB);
+    BigDecimal bdR = bdA.multiply(bdB);
+
+    String res2 = bdR.toPlainString();
+
+    // Compare the results
+    assertEquals(res1, res2);
+  }
+
+  // Test a set of random divisions at high precision.
+  @Test
+  public void testHighPrecisionDecimal128Divide() {
+    final int N = 10000;
+    for (int i = 0; i < N; i++) {
+      verifyHighPrecisionDivideSingle();
+    }
+  }
+
+  // Test a single, high-precision divide of random inputs.
+  private void verifyHighPrecisionDivideSingle() {
+
+    Decimal128 a, b, r;
+    String sA, sB;
+
+    Random rand = new Random();
+    int aDigits = rand.nextInt(37) + 1; // number of digits in a (1..37)
+    int bDigits = 38 - aDigits;         // number of digits in b (1..37)
+    int temp;
+
+    // make sure b will have less digits than A
+    if (bDigits > aDigits) {
+      temp = aDigits;
+      aDigits = bDigits;
+      bDigits = temp;
+    }
+    if (bDigits == aDigits) {
+      return;
+    }
+    assertTrue(aDigits + bDigits == 38 && aDigits > 0 && bDigits > 0);
+
+    a = new Decimal128();
+    sA = makeNumericString(aDigits);
+    a.update(sA, (short) 0);
+    b = new Decimal128();
+    sB = makeNumericString(bDigits);
+    b.update(sB, (short) 0);
+    if (b.isZero()) {
+
+      // don't do zero-divide if one comes up at random
+      return;
+    }
+
+    r = new Decimal128();
+    r.addDestructive(a, (short) 0);
+    r.divideDestructive(b, (short) 0);
+
+    String res1 = r.toFormalString();
+
+    // Now do the operation with Java BigDecimal
+    BigDecimal bdA = new BigDecimal(sA);
+    BigDecimal bdB = new BigDecimal(sB);
+    BigDecimal bdR = bdA.divide(bdB, 0, RoundingMode.HALF_UP);
+
+    String res2 = bdR.toPlainString();
+
+    // Compare the results
+    assertEquals(res1, res2);
+  }
+
+  /* Return a random number with length digits, as a string. Results may be
+   * negative or positive.
+   */
+  private String makeNumericString(int length) {
+    Random r = new Random();
+    StringBuilder b = new StringBuilder();
+    for(int i = 0; i < length; i++) {
+      b.append(r.nextInt(10));
+    }
+
+    // choose a random sign
+    String sign = r.nextInt(2) == 0 ? "-" : "";
+    return sign + b.toString();
+  }
+
   @Test
   public void testPiNewton() {