Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: changed all the utility methods that didn't operate on state data to static methods

...

Code Block
bgColor#FFcccc
public static int multAccum(int oldAcc, int newVal, int scale) {
  // May result in overflow 
  return oldAcc + (newVal * scale);
}

...

Code Block
bgColor#ccccff
public static int multAccum(int oldAcc, int newVal, int scale) throws ArithmeticException {
  preMultiply(newVal, Scale);
  final int temp = newVal * scale;
  preAdd(oldAcc, temp);
  return oldAcc + temp;
}

...

For all integral types other than long, the next larger integral type can represent the result of any single integral operation. For example, operations on values of type int can be safely performed using type long. As a result, we can perform an operation using the larger type and range-check before downcasting down casting to the original type. Note, however, that this guarantee holds only for a single arithmetic operation; larger expressions without per-operation bounds checking may overflow the larger type.

...

Code Block
bgColor#ccccff

public static long intRangeCheck(long value) throws ArithmeticOverflow {
  if ((value < Integer.MIN_VALUE) || (value > Integer.MAX_VALUE)) {
    throw new ArithmeticException("Integer overflow");
  }
  return value;
}

public static int multAccum(int oldAcc, int newVal, int scale) throws ArithmeticException {
  final long res = 
    intRangeCheck(((long) oldAcc) + intRangeCheck((long) newVal * (long) scale));
  return (int) res; // safe down-cast
}

...

Code Block
bgColor#ccccff
private static final BigInteger bigMaxInt = BigInteger.valueOf(Int.MAX_VALUE);
private static final BigInteger bigMinInt = BigInteger.valueOf(Int.MIN_VALUE);

public static BigInteger intRangeCheck(BigInteger val) throws ArithmeticException {
  if (val.compareTo(bigMaxInt) == 1 ||
      val.compareTo(bigMinInt) == -1) {
    throw new ArithmeticException("Integer overflow");
  }
  return val;
}

public static int multAccum(int oldAcc, int newVal, int scale) throws ArithmeticException { 
  BigInteger product =
    BigInteger.valueOf(newVal).multiply(BigInteger.valueOf(scale));
  BigInteger res = intRangeCheck(BigInteger.valueOf(oldAcc).add(product));
  return res.intValue(); // safe conversion
}

...