Example #1
0
  private static void checkNormaliseBaseTenResult(ExpandedDouble orig, NormalisedDecimal result) {
    String sigDigs = result.getSignificantDecimalDigits();
    BigInteger frac = orig.getSignificand();
    while (frac.bitLength() + orig.getBinaryExponent() < 200) {
      frac = frac.multiply(BIG_POW_10);
    }
    int binaryExp = orig.getBinaryExponent() - orig.getSignificand().bitLength();

    String origDigs = frac.shiftLeft(binaryExp + 1).toString(10);

    if (!origDigs.startsWith(sigDigs)) {
      throw new AssertionFailedError("Expected '" + origDigs + "' but got '" + sigDigs + "'.");
    }

    double dO = Double.parseDouble("0." + origDigs.substring(sigDigs.length()));
    double d1 = Double.parseDouble(result.getFractionalPart().toPlainString());
    BigInteger subDigsO = BigInteger.valueOf((int) (dO * 32768 + 0.5));
    BigInteger subDigsB = BigInteger.valueOf((int) (d1 * 32768 + 0.5));

    if (subDigsO.equals(subDigsB)) {
      return;
    }
    BigInteger diff = subDigsB.subtract(subDigsO).abs();
    if (diff.intValue() > 100) {
      // 100/32768 ~= 0.003
      throw new AssertionFailedError("minor mistake");
    }
  }
Example #2
0
 public static String getBaseDecimal(ExpandedDouble hd) {
   int gg = 64 - hd.getBinaryExponent() - 1;
   BigDecimal bd =
       new BigDecimal(hd.getSignificand()).divide(new BigDecimal(BigInteger.ONE.shiftLeft(gg)));
   int excessPrecision = bd.precision() - 23;
   if (excessPrecision > 0) {
     bd = bd.setScale(bd.scale() - excessPrecision, BigDecimal.ROUND_HALF_UP);
   }
   return bd.unscaledValue().toString();
 }
Example #3
0
  public void testSubnormal() {
    ExpandedDouble hd = new ExpandedDouble(0x0000000000000001L);

    if (hd.getBinaryExponent() == -1023) {
      throw new AssertionFailedError("identified bug - subnormal numbers not decoded properly");
    }
    assertEquals(-1086, hd.getBinaryExponent());
    BigInteger frac = hd.getSignificand();
    assertEquals(64, frac.bitLength());
    assertEquals(1, frac.bitCount());
  }
Example #4
0
  public void testNegative() {
    ExpandedDouble hd = new ExpandedDouble(0xC010000000000000L);

    if (hd.getBinaryExponent() == -2046) {
      throw new AssertionFailedError("identified bug - sign bit not masked out of exponent");
    }
    assertEquals(2, hd.getBinaryExponent());
    BigInteger frac = hd.getSignificand();
    assertEquals(64, frac.bitLength());
    assertEquals(1, frac.bitCount());
  }
Example #5
0
  public static boolean confirmRoundTrip(int i, long rawBitsA) {
    double a = Double.longBitsToDouble(rawBitsA);
    if (a == 0.0) {
      // Can't represent 0.0 or -0.0 with NormalisedDecimal
      return true;
    }
    ExpandedDouble ed1;
    NormalisedDecimal nd2;
    ExpandedDouble ed3;
    try {
      ed1 = new ExpandedDouble(rawBitsA);
      nd2 = ed1.normaliseBaseTen();
      checkNormaliseBaseTenResult(ed1, nd2);

      ed3 = nd2.normaliseBaseTwo();
    } catch (RuntimeException e) {
      System.err.println("example[" + i + "] (" + formatDoubleAsHex(a) + ") exception:");
      e.printStackTrace();
      return false;
    }
    if (ed3.getBinaryExponent() != ed1.getBinaryExponent()) {
      System.err.println("example[" + i + "] (" + formatDoubleAsHex(a) + ") bin exp mismatch");
      return false;
    }
    BigInteger diff = ed3.getSignificand().subtract(ed1.getSignificand()).abs();
    if (diff.signum() == 0) {
      return true;
    }
    // original quantity only has 53 bits of precision
    // these quantities may have errors in the 64th bit, which hopefully don't make any difference

    if (diff.bitLength() < 2) {
      // errors in the 64th bit happen from time to time
      // this is well below the 53 bits of precision required
      return true;
    }

    // but bigger errors are a concern
    System.out.println(
        "example[" + i + "] (" + formatDoubleAsHex(a) + ") frac mismatch: " + diff.toString());

    for (int j = -2; j < 3; j++) {
      System.out.println((j < 0 ? "" : "+") + j + ": " + getNearby(ed1, j));
    }
    for (int j = -2; j < 3; j++) {
      System.out.println((j < 0 ? "" : "+") + j + ": " + getNearby(nd2, j));
    }

    return false;
  }
Example #6
0
 public static BigInteger getNearby(ExpandedDouble hd, int offset) {
   return getNearby(hd.getSignificand(), hd.getBinaryExponent(), offset);
 }