/** * Construct this object from UnsignedInt128. The highest bit of the * UnsignedInt128 is converted as the sign bit just like conversion between * int/uint in C++. * * @param mag * UnsignedInt128 object */ public SignedInt128(UnsignedInt128 mag) { this.negative = mag.getV3() < 0; this.mag = new UnsignedInt128(mag.getV0(), mag.getV1(), mag.getV2(), mag.getV3() & SqlMathUtil.FULLBITS_31); }
/** * 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); }
/** * @see #compareTo(UnsignedInt128) * @param o * the object to be compared. * @return a negative integer, zero, or a positive integer as this object is * less than, equal to, or greater than the specified object. */ public int compareTo(int[] o) { return compareTo(o[0], o[1], o[2], o[3]); }
/** * This version returns the result as a new object, not modifying the give * objects. This method doesn't work if right operand is larger than this * value. * * @return operation result as a new object */ public UnsignedInt128 decrementConstructive() { UnsignedInt128 ret = new UnsignedInt128(this); ret.decrementDestructive(); return ret; }
/** * This version returns the result as a new object, not modifying the give * objects. * * @return operation result as a new object */ public UnsignedInt128 incrementConstructive() { UnsignedInt128 ret = new UnsignedInt128(this); ret.incrementDestructive(); return ret; }
@Test public void testMultiplyDestructiveInt() { two.multiplyDestructive(1); assertEquals(2L, two.asLong()); assertEquals(1L, one.asLong()); two.multiplyDestructive(2); assertEquals(4L, two.asLong()); UnsignedInt128 five = new UnsignedInt128(5); five.multiplyDestructive(6432346); assertEquals(6432346 * 5, five.getV0()); assertEquals(0, five.getV1()); assertEquals(0, five.getV2()); assertEquals(0, five.getV3()); UnsignedInt128 big = new UnsignedInt128((1L << 62) + (3L << 34) + 3L); big.multiplyDestructive(96); assertEquals(3 * 96, big.getV0()); assertEquals(96 * (3 << 2), big.getV1()); assertEquals(96 / 4, big.getV2()); assertEquals(0, big.getV3()); UnsignedInt128 tmp = new UnsignedInt128(1); tmp.shiftLeftDestructive(126); tmp.multiplyDestructive(2); try { tmp.multiplyDestructive(2); fail(); } catch (ArithmeticException ex) { // ok } }
/** * 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(); } } }
@Test public void testSubtractDestructive() { two.subtractDestructive(one); assertEquals(1L, one.asLong()); assertEquals(1L, one.asLong()); try { one.subtractDestructive(new UnsignedInt128(10L)); fail(); } catch (ArithmeticException ex) { // ok } UnsignedInt128 big = new UnsignedInt128((1L << 62) + (3L << 34) + 3L); big.shiftLeftDestructive(6); UnsignedInt128 tmp = new UnsignedInt128((1L << 61) + 5L); tmp.shiftLeftDestructive(6); big.subtractDestructive(tmp); big.subtractDestructive(tmp); assertEquals((3 << 6) - 2 * (5 << 6), big.getV0()); assertEquals((3 << 8) - 1, big.getV1()); assertEquals(0, big.getV2()); assertEquals(0, big.getV3()); }
@Test public void testShiftDestructive() { UnsignedInt128 big = new UnsignedInt128((1L << 62) + (23L << 32) + 89L); big.shiftLeftDestructive(2); assertEquals(89 * 4, big.getV0()); assertEquals(23 * 4, big.getV1()); assertEquals(1, big.getV2()); assertEquals(0, big.getV3()); big.shiftLeftDestructive(32); assertEquals(0, big.getV0()); assertEquals(89 * 4, big.getV1()); assertEquals(23 * 4, big.getV2()); assertEquals(1, big.getV3()); big.shiftRightDestructive(2, true); assertEquals(0, big.getV0()); assertEquals(89, big.getV1()); assertEquals(23 + (1 << 30), big.getV2()); assertEquals(0, big.getV3()); big.shiftRightDestructive(32, true); assertEquals(89, big.getV0()); assertEquals(23 + (1 << 30), big.getV1()); assertEquals(0, big.getV2()); assertEquals(0, big.getV3());
@Test public void testAddDestructive() { one.addDestructive(two); assertEquals(3L, one.asLong()); assertEquals(2L, two.asLong()); UnsignedInt128 big = new UnsignedInt128((1L << 62) + 3L); UnsignedInt128 tmp = new UnsignedInt128(0L); for (int i = 0; i < 54; ++i) { tmp.addDestructive(big); } assertEquals(3 * 54, tmp.getV0()); assertEquals(0x80000000, tmp.getV1()); // (54 % 4) << 62 assertEquals(13, tmp.getV2()); // 54/4 assertEquals(0, tmp.getV3()); assertEquals((1L << 62) + 3L, big.asLong()); UnsignedInt128 huge = one.shiftLeftConstructive(127); UnsignedInt128 huge2 = one.shiftLeftConstructive(127); try { huge2.addDestructive(huge); fail(); } catch (ArithmeticException ex) { // ok } }
@Test public void testMultiplyScaleDownTenDestructiveScaleTen() { for (int scale = 0; scale < 38; ++scale) { UnsignedInt128 right = new UnsignedInt128(1); right.scaleUpTenDestructive((short) scale); UnsignedInt128 leftJust = new UnsignedInt128(1); leftJust.scaleUpTenDestructive((short) 15); UnsignedInt128 leftInc = leftJust.incrementConstructive(); UnsignedInt128 leftDec = leftJust.decrementConstructive(); leftJust.multiplyScaleDownTenDestructive(right, (short) (scale + 10)); assertEquals("scale=" + scale, 100000L, leftJust.asLong()); leftInc.multiplyScaleDownTenDestructive(right, (short) (scale + 10)); assertEquals("scale=" + scale, 100000L, leftInc.asLong()); leftDec.multiplyScaleDownTenDestructive(right, (short) (scale + 10)); assertEquals("scale=" + scale, 100000L, leftDec.asLong()); } else { leftJust.multiplyScaleDownTenDestructive(right, (short) (scale + 10)); assertEquals("scale=" + scale, 0L, leftJust.asLong()); leftInc.multiplyScaleDownTenDestructive(right, (short) (scale + 10)); assertEquals("scale=" + scale, 0L, leftInc.asLong()); leftDec.multiplyScaleDownTenDestructive(right, (short) (scale + 10)); assertEquals("scale=" + scale, 0L, leftDec.asLong()); UnsignedInt128 leftHalfJust = new UnsignedInt128(1); leftHalfJust.scaleUpTenDestructive((short) 6); leftHalfJust.addDestructive(new UnsignedInt128(5)); leftHalfJust.scaleUpTenDestructive((short) 9); UnsignedInt128 leftHalfInc = leftHalfJust.incrementConstructive();
this.unscaledValue.divideDestructive(right.unscaledValue, remainder.unscaledValue); this.unscaledValue.scaleDownTenDestructive(scaleBack); remainder.unscaledValue.scaleDownTenDestructive(scaleBack); } else { this.unscaledValue.divideScaleUpTenDestructive(right.unscaledValue, (short) -scaleBack, remainder.unscaledValue); this.signum = (byte) (this.unscaledValue.isZero() ? 0 : (this.signum * right.signum)); remainder.scale = scale; remainder.signum = (byte) (remainder.unscaledValue.isZero() ? 0 : 1); // remainder this.unscaledValue.throwIfExceedsTenToThirtyEight();
return compareTo(o); if (o.isZero()) { return this.isZero() ? 0 : 1; } else if (this.isZero()) { .compareTo(SqlMathUtil.ROUND_POWER_TENS_INT128[-tenScale]) < 0; return oZero ? 0 : -1; if (this.fitsInt32() && o.fitsInt32() && tenScale <= SqlMathUtil.MAX_POWER_TEN_INT31) { long v0Long = this.v[0] & SqlMathUtil.LONG_MASK; scaleDownTenArray4RoundUp(ov, (short) -tenScale); } else { boolean overflow = scaleUpTenArray(ov, tenScale); if (overflow) { return compareTo(ov);
@Test public void testDivideDestructiveInt() { two.divideDestructive(1); assertEquals(1L, one.asLong()); assertEquals(2L, two.asLong()); one.divideDestructive(2); assertEquals(0L, one.asLong()); assertEquals(2L, two.asLong()); UnsignedInt128 var1 = new UnsignedInt128(1234234662345L); var1.divideDestructive(642337); assertEquals(1234234662345L / 642337L, var1.asLong()); UnsignedInt128 complicated1 = new UnsignedInt128(0xF9892FCA, 0x59D109AD, 0x0534AB4C, 0); BigInteger bigInteger1 = complicated1.toBigIntegerSlow(); complicated1.divideDestructive(1534223465); BigInteger bigInteger2 = BigInteger.valueOf(1534223465); BigInteger ans = bigInteger1.divide(bigInteger2); assertEquals(ans, complicated1.toBigIntegerSlow()); try { complicated1.divideDestructive(0); fail(); } catch (ArithmeticException ex) { // ok } }
UnsignedInt128 tmp = new UnsignedInt128(this); while (!tmp.isZero()) { int remainder = tmp.divideDestructive(tenPower); for (int i = 0; i < tenScale && bufCount < buf.length; ++i) { int digit = remainder % 10;
} else if (str[cursor] >= '0' && str[cursor] <= '9') { if (accumulatedCount == 9) { this.unscaledValue.scaleUpTenDestructive((short) accumulatedCount); this.unscaledValue.addDestructive(accumulated); accumulated = 0; accumulatedCount = 0; this.unscaledValue.scaleUpTenDestructive((short) accumulatedCount); this.unscaledValue.addDestructive(accumulated); this.unscaledValue.scaleUpTenDestructive((short) scaleAdjust); } else if (scaleAdjust < 0) { this.unscaledValue.scaleDownTenDestructive((short) -scaleAdjust); this.signum = (byte) (this.unscaledValue.isZero() ? 0 : (negative ? -1 : 1)); return this;
zeroClear(); return; scaleUpTenDestructive((short) accumulatedCount); addDestructive(accumulated); accumulated = 0; accumulatedCount = 0; scaleUpTenDestructive((short) accumulatedCount); addDestructive(accumulated);
@Test public void testDivideDestructiveUnsignedInt128Again() { UnsignedInt128 complicated1 = new UnsignedInt128(0xF9892FCA, 0x59D109AD, 0, 0); UnsignedInt128 complicated2 = new UnsignedInt128(0xF09DC19A, 3, 0, 0); BigInteger bigInteger1 = complicated1.toBigIntegerSlow(); BigInteger bigInteger2 = complicated2.toBigIntegerSlow(); complicated1.divideDestructive(complicated2, new UnsignedInt128()); BigInteger ans = bigInteger1.divide(bigInteger2); assertEquals(ans, complicated1.toBigIntegerSlow()); }
/** * Zero the fractional part of value. * * Argument scratch is needed to hold unused remainder output, to avoid need to * create a new object. */ public void zeroFractionPart(UnsignedInt128 scratch) { short placesToRemove = this.getScale(); // If there's no fraction part, return immediately to avoid the cost of a divide. if (placesToRemove == 0) { return; } /* Divide by a power of 10 equal to 10**scale to logically shift the digits * places right by "scale" positions to eliminate them. */ UnsignedInt128 powerTenDivisor = SqlMathUtil.POWER_TENS_INT128[placesToRemove]; this.getUnscaledValue().divideDestructive(powerTenDivisor, scratch); /* Multiply by the same power of ten to shift the decimal point back to * the original place. Places to the right of the decimal will be zero. */ this.getUnscaledValue().scaleUpTenDestructive(placesToRemove); if (this.unscaledValue.isZero()) { this.signum = 0; } }
/** * This version returns the result as a new object, not modifying the give * objects. * * @param right * right operand * @return operation result as a new object */ public UnsignedInt128 addConstructive(UnsignedInt128 right) { UnsignedInt128 ret = new UnsignedInt128(this); ret.addDestructive(right); return ret; }