private static void decrementArray(int[] array) { for (int i = 0; i < INT_COUNT; ++i) { if (array[i] != 0) { array[i] = (int) ((array[i] & SqlMathUtil.LONG_MASK) - 1L); break; } array[i] = SqlMathUtil.FULLBITS_32; if (i == INT_COUNT - 1) { SqlMathUtil.throwOverflowException(); } } }
/** * Returns the value of this object as long, throwing error if the value * exceeds long. * * @return the value this object represents */ public long asLong() { if (this.count > 2 || v[1] < 0) { SqlMathUtil.throwOverflowException(); } return (((long) v[1]) << 32L) | v[0]; }
private static void incrementArray(int[] array) { for (int i = 0; i < INT_COUNT; ++i) { if (array[i] != SqlMathUtil.FULLBITS_32) { array[i] = (int) ((array[i] & SqlMathUtil.LONG_MASK) + 1L); break; } array[i] = 0; if (i == INT_COUNT - 1) { SqlMathUtil.throwOverflowException(); } } }
/** * Multi-precision one super-digit multiply in place. * * @param inOut * @param multiplier */ private static void multiplyMultiPrecision(int[] inOut, int multiplier) { long multiplierUnsigned = multiplier & SqlMathUtil.LONG_MASK; long product = 0L; for (int i = 0; i < inOut.length; ++i) { product = (inOut[i] & SqlMathUtil.LONG_MASK) * multiplierUnsigned + (product >>> 32); inOut[i] = (int) product; } if ((product >> 32) != 0) { SqlMathUtil.throwOverflowException(); } }
/** * Used to check overflows. This is NOT used in {@link UnsignedInt128} itself * because this overflow semantics is Decimal's. (throws - but not a checked * exception) ArithmeticException if this value is equal to or exceed 10**38. */ public void throwIfExceedsTenToThirtyEight() { if (exceedsTenToThirtyEight()) { SqlMathUtil.throwOverflowException(); } }
/** * Throws an exception if the value of this object exceeds the maximum value * for the given precision. Remember that underflow is not an error, but * overflow is an immediate error. * * @param precision * maximum precision */ public void checkPrecisionOverflow(int precision) { if (precision <= 0 || precision > 38) { throw new IllegalArgumentException("Invalid precision " + precision); } if (this.unscaledValue.compareTo(SqlMathUtil.POWER_TENS_INT128[precision]) >= 0) { SqlMathUtil.throwOverflowException(); } }
/** * Adds the given value to this value. This version is destructive, meaning it * modifies this object. * * @param r * the value to add */ public void addDestructive(int[] r) { long sum = 0L; for (int i = 0; i < INT_COUNT; ++i) { sum = (this.v[i] & SqlMathUtil.LONG_MASK) + (r[i] & SqlMathUtil.LONG_MASK) + (sum >>> 32); this.v[i] = (int) sum; } updateCount(); if ((sum >> 32) != 0) { SqlMathUtil.throwOverflowException(); } }
/** * Subtracts the given value from this value. In other words, this := this - * right. This method doesn't work if right operand is larger than this value. * This version is destructive, meaning it modifies this object. * * @param r * the value to subtract */ public void subtractDestructive(int[] r) { long sum = 0L; for (int i = 0; i < INT_COUNT; ++i) { sum = (this.v[i] & SqlMathUtil.LONG_MASK) - (r[i] & SqlMathUtil.LONG_MASK) - ((int) -(sum >> 32)); this.v[i] = (int) sum; } updateCount(); if ((sum >> 32) != 0) { SqlMathUtil.throwOverflowException(); } }
/** * Adds the given value to this value. This version is destructive, meaning it * modifies this object. * * @param r * the value to add */ public void addDestructive(int r) { if ((this.v[0] & SqlMathUtil.LONG_MASK) + (r & SqlMathUtil.LONG_MASK) >= (1L << 32L)) { this.v[0] += r; if (this.v[1] == SqlMathUtil.FULLBITS_32) { this.v[1] = 0; if (this.v[2] == SqlMathUtil.FULLBITS_32) { this.v[2] = 0; if (this.v[3] == SqlMathUtil.FULLBITS_32) { SqlMathUtil.throwOverflowException(); } else { ++this.v[3]; } } else { ++this.v[2]; } } else { ++this.v[1]; } } else { this.v[0] += r; } updateCount(); }
/** * Performs multiplication. * * @param right * right operand. this object is not modified. */ public void multiplyDestructive(SignedInt128 right) { this.mag.multiplyDestructive(right.mag); this.negative = this.negative ^ right.negative; if (this.mag.getV3() < 0) { SqlMathUtil.throwOverflowException(); } }
/** * Left-shift for the given number of bits. This method throws an error even * if overflow happens. This version is destructive, meaning it modifies this * object. * * @param bits * the number of bits. must be positive */ public void shiftLeftDestructiveCheckOverflow(int bits) { if (bitLength() + bits >= 128) { SqlMathUtil.throwOverflowException(); } shiftLeftDestructive(bits); }
/** * Scale up the value for 10**tenScale (this := this * 10**tenScale). Scaling * up DOES throw an error when an overflow occurs. For example, 42.scaleUp(1) * = 420, 42.scaleUp(40) = ArithmeticException. This version is destructive, * meaning it modifies this object. * * @param tenScale * scaling. must be positive */ public void scaleUpTenDestructive(short tenScale) { this.mag.scaleUpTenDestructive(tenScale); if (this.mag.getV3() < 0) { SqlMathUtil.throwOverflowException(); } }
/** * Multiplies this value with the given integer value. This version is * destructive, meaning it modifies this object. * * @param right * the value to multiply */ public void multiplyDestructive(int right) { if (right == 0) { zeroClear(); return; } else if (right == 1) { return; } long sum = 0L; long rightUnsigned = right & SqlMathUtil.LONG_MASK; for (int i = 0; i < INT_COUNT; ++i) { sum = (this.v[i] & SqlMathUtil.LONG_MASK) * rightUnsigned + (sum >>> 32); this.v[i] = (int) sum; } updateCount(); if ((sum >> 32) != 0) { SqlMathUtil.throwOverflowException(); } }
/** * Left-shift for the given number of bits. This bit-shift is equivalent to * Java's signed bit shift "<<". This method does not throw an error * even if overflow happens. This version is destructive, meaning it modifies * this object. * * @param bits * the number of bits. must be positive */ public void shiftLeftDestructive(int bits) { this.mag.shiftLeftDestructive(bits); if (this.mag.getV3() < 0) { SqlMathUtil.throwOverflowException(); } assert (this.mag.getV3() >= 0); }
/** * Calculates addition and stores the result into this object. This method is * destructive. * * @param right * right operand */ public void addDestructive(SignedInt128 right) { if (this.negative == right.negative) { this.mag.addDestructive(right.mag); if (this.mag.getV3() < 0) { SqlMathUtil.throwOverflowException(); } return; } byte signum = UnsignedInt128.difference(this.mag, right.mag, this.mag); this.negative = (signum > 0 ? this.negative : right.negative); }
/** * Calculates subtraction and stores the result into this object. This method * is destructive. * * @param right * right operand */ public void subtractDestructive(SignedInt128 right) { if (this.negative != right.negative) { this.mag.addDestructive(right.mag); if (this.mag.getV3() < 0) { SqlMathUtil.throwOverflowException(); } return; } byte signum = UnsignedInt128.difference(this.mag, right.mag, this.mag); this.negative = (signum > 0 ? this.negative : !this.negative); }
/** * Performs multiplication. * * @param right * right operand. */ public void multiplyDestructive(int right) { if (right < 0) { this.mag.multiplyDestructive(-right); this.negative = !this.negative; } else { this.mag.multiplyDestructive(right); } if (this.mag.isZero()) { this.negative = false; } if (this.mag.getV3() < 0) { SqlMathUtil.throwOverflowException(); } }
/** * Scale up this object for 10**tenScale and then divides this value with the * given value. This version is destructive, meaning it modifies this object. * * @param right * the value to divide * @param tenScale * ten-based scale up distance * @param remainder * object to receive remainder */ public void divideScaleUpTenDestructive(UnsignedInt128 right, short tenScale, UnsignedInt128 remainder) { // in this case, we have to scale up _BEFORE_ division. otherwise we // might lose precision. if (tenScale > SqlMathUtil.MAX_POWER_TEN_INT128) { // in this case, the result will be surely more than 128 bit even // after division SqlMathUtil.throwOverflowException(); } int[] scaledUp = multiplyConstructive256(SqlMathUtil.POWER_TENS_INT128[tenScale]); int[] quotient = new int[5]; int[] rem = SqlMathUtil.divideMultiPrecision(scaledUp, right.v, quotient); update(quotient[0], quotient[1], quotient[2], quotient[3]); remainder.update(rem[0], rem[1], rem[2], rem[3]); }
/** * Subtracts one from this value. This version is destructive, meaning it * modifies this object. */ public void decrementDestructive() { if (this.negative) { if (this.mag.equals(SqlMathUtil.FULLBITS_32, SqlMathUtil.FULLBITS_32, SqlMathUtil.FULLBITS_32, SqlMathUtil.FULLBITS_31)) { SqlMathUtil.throwOverflowException(); } this.mag.incrementDestructive(); assert (this.mag.getV3() >= 0); } else { if (this.mag.isZero()) { this.negative = true; this.mag.incrementDestructive(); } else { this.mag.decrementDestructive(); } } }
/** * Adds one to this value. This version is destructive, meaning it modifies * this object. */ public void incrementDestructive() { if (!this.negative) { if (this.mag.equals(SqlMathUtil.FULLBITS_32, SqlMathUtil.FULLBITS_32, SqlMathUtil.FULLBITS_32, SqlMathUtil.FULLBITS_31)) { SqlMathUtil.throwOverflowException(); } this.mag.incrementDestructive(); assert (this.mag.getV3() >= 0); } else { assert (!this.mag.isZero()); this.mag.decrementDestructive(); if (this.mag.isZero()) { this.negative = false; } } }