/** Returns (a * 2^32) mod m. a may be any unsigned long. */ private long times2ToThe32Mod(long a, long m) { int remainingPowersOf2 = 32; do { int shift = Math.min(remainingPowersOf2, Long.numberOfLeadingZeros(a)); // shift is either the number of powers of 2 left to multiply a by, or the biggest shift // possible while keeping a in an unsigned long. a = UnsignedLongs.remainder(a << shift, m); remainingPowersOf2 -= shift; } while (remainingPowersOf2 > 0); return a; }
/** * Returns this modulo {@code val}. * * @since 14.0 */ public UnsignedLong mod(UnsignedLong val) { return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value)); }
/** Returns (a * 2^32) mod m. a may be any unsigned long. */ private long times2ToThe32Mod(long a, long m) { int remainingPowersOf2 = 32; do { int shift = Math.min(remainingPowersOf2, Long.numberOfLeadingZeros(a)); // shift is either the number of powers of 2 left to multiply a by, or the biggest shift // possible while keeping a in an unsigned long. a = UnsignedLongs.remainder(a << shift, m); remainingPowersOf2 -= shift; } while (remainingPowersOf2 > 0); return a; }
/** Returns (a * 2^32) mod m. a may be any unsigned long. */ private long times2ToThe32Mod(long a, long m) { int remainingPowersOf2 = 32; do { int shift = Math.min(remainingPowersOf2, Long.numberOfLeadingZeros(a)); // shift is either the number of powers of 2 left to multiply a by, or the biggest shift // possible while keeping a in an unsigned long. a = UnsignedLongs.remainder(a << shift, m); remainingPowersOf2 -= shift; } while (remainingPowersOf2 > 0); return a; }
/** * Returns this modulo {@code val}. * * @since 14.0 */ public UnsignedLong mod(UnsignedLong val) { return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value)); }
/** * Returns this modulo {@code val}. * * @since 14.0 */ public UnsignedLong mod(UnsignedLong val) { return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value)); }
@Override long squareMod(long a, long m) { long aHi = a >>> 32; // < 2^31 long aLo = a & 0xFFFFFFFFL; // < 2^32 /* * a^2 == aHi^2 * 2^64 + aHi * aLo * 2^33 + aLo^2 * == (aHi^2 * 2^32 + aHi * aLo * 2) * 2^32 + aLo^2 * We carry out this computation in modular arithmetic. Since times2ToThe32Mod accepts any * unsigned long, we don't have to do a mod on every operation, only when intermediate * results can exceed 2^63. */ long result = times2ToThe32Mod(aHi * aHi /* < 2^62 */, m); // < m < 2^63 long hiLo = aHi * aLo * 2; if (hiLo < 0) { hiLo = UnsignedLongs.remainder(hiLo, m); } // hiLo < 2^63 result += hiLo; // result < 2^64 result = times2ToThe32Mod(result, m); // result < m < 2^63 return plusMod(result, UnsignedLongs.remainder(aLo * aLo /* < 2^64 */, m), m); } };
@Override long mulMod(long a, long b, long m) { long aHi = a >>> 32; // < 2^31 long bHi = b >>> 32; // < 2^31 long aLo = a & 0xFFFFFFFFL; // < 2^32 long bLo = b & 0xFFFFFFFFL; // < 2^32 /* * a * b == aHi * bHi * 2^64 + (aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo. * == (aHi * bHi * 2^32 + aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo * * We carry out this computation in modular arithmetic. Since times2ToThe32Mod accepts any * unsigned long, we don't have to do a mod on every operation, only when intermediate * results can exceed 2^63. */ long result = times2ToThe32Mod(aHi * bHi /* < 2^62 */, m); // < m < 2^63 result += aHi * bLo; // aHi * bLo < 2^63, result < 2^64 if (result < 0) { result = UnsignedLongs.remainder(result, m); } // result < 2^63 again result += aLo * bHi; // aLo * bHi < 2^63, result < 2^64 result = times2ToThe32Mod(result, m); // result < m < 2^63 return plusMod(result, UnsignedLongs.remainder(aLo * bLo /* < 2^64 */, m), m); }
public void testRemainder() { assertEquals(4, UnsignedLongs.remainder(14, 5)); assertEquals(0, UnsignedLongs.remainder(0, 50)); assertEquals(1, UnsignedLongs.remainder(0xfffffffffffffffeL, 0xfffffffffffffffdL)); assertEquals( 0xfffffffffffffffdL, UnsignedLongs.remainder(0xfffffffffffffffdL, 0xfffffffffffffffeL)); assertEquals(65534L, UnsignedLongs.remainder(0xfffffffffffffffeL, 65535)); assertEquals(0, UnsignedLongs.remainder(0xfffffffffffffffeL, 2)); assertEquals(4, UnsignedLongs.remainder(0xfffffffffffffffeL, 5)); }
@Override long squareMod(long a, long m) { long aHi = a >>> 32; // < 2^31 long aLo = a & 0xFFFFFFFFL; // < 2^32 /* * a^2 == aHi^2 * 2^64 + aHi * aLo * 2^33 + aLo^2 * == (aHi^2 * 2^32 + aHi * aLo * 2) * 2^32 + aLo^2 * We carry out this computation in modular arithmetic. Since times2ToThe32Mod accepts any * unsigned long, we don't have to do a mod on every operation, only when intermediate * results can exceed 2^63. */ long result = times2ToThe32Mod(aHi * aHi /* < 2^62 */, m); // < m < 2^63 long hiLo = aHi * aLo * 2; if (hiLo < 0) { hiLo = UnsignedLongs.remainder(hiLo, m); } // hiLo < 2^63 result += hiLo; // result < 2^64 result = times2ToThe32Mod(result, m); // result < m < 2^63 return plusMod(result, UnsignedLongs.remainder(aLo * aLo /* < 2^64 */, m), m); } };
@Override long mulMod(long a, long b, long m) { long aHi = a >>> 32; // < 2^31 long bHi = b >>> 32; // < 2^31 long aLo = a & 0xFFFFFFFFL; // < 2^32 long bLo = b & 0xFFFFFFFFL; // < 2^32 /* * a * b == aHi * bHi * 2^64 + (aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo. * == (aHi * bHi * 2^32 + aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo * * We carry out this computation in modular arithmetic. Since times2ToThe32Mod accepts any * unsigned long, we don't have to do a mod on every operation, only when intermediate * results can exceed 2^63. */ long result = times2ToThe32Mod(aHi * bHi /* < 2^62 */, m); // < m < 2^63 result += aHi * bLo; // aHi * bLo < 2^63, result < 2^64 if (result < 0) { result = UnsignedLongs.remainder(result, m); } // result < 2^63 again result += aLo * bHi; // aLo * bHi < 2^63, result < 2^64 result = times2ToThe32Mod(result, m); // result < m < 2^63 return plusMod(result, UnsignedLongs.remainder(aLo * bLo /* < 2^64 */, m), m); }
@Override long squareMod(long a, long m) { long aHi = a >>> 32; // < 2^31 long aLo = a & 0xFFFFFFFFL; // < 2^32 /* * a^2 == aHi^2 * 2^64 + aHi * aLo * 2^33 + aLo^2 * == (aHi^2 * 2^32 + aHi * aLo * 2) * 2^32 + aLo^2 * We carry out this computation in modular arithmetic. Since times2ToThe32Mod accepts any * unsigned long, we don't have to do a mod on every operation, only when intermediate * results can exceed 2^63. */ long result = times2ToThe32Mod(aHi * aHi /* < 2^62 */, m); // < m < 2^63 long hiLo = aHi * aLo * 2; if (hiLo < 0) { hiLo = UnsignedLongs.remainder(hiLo, m); } // hiLo < 2^63 result += hiLo; // result < 2^64 result = times2ToThe32Mod(result, m); // result < m < 2^63 return plusMod(result, UnsignedLongs.remainder(aLo * aLo /* < 2^64 */, m), m); } };
@Override long mulMod(long a, long b, long m) { long aHi = a >>> 32; // < 2^31 long bHi = b >>> 32; // < 2^31 long aLo = a & 0xFFFFFFFFL; // < 2^32 long bLo = b & 0xFFFFFFFFL; // < 2^32 /* * a * b == aHi * bHi * 2^64 + (aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo. * == (aHi * bHi * 2^32 + aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo * * We carry out this computation in modular arithmetic. Since times2ToThe32Mod accepts any * unsigned long, we don't have to do a mod on every operation, only when intermediate * results can exceed 2^63. */ long result = times2ToThe32Mod(aHi * bHi /* < 2^62 */, m); // < m < 2^63 result += aHi * bLo; // aHi * bLo < 2^63, result < 2^64 if (result < 0) { result = UnsignedLongs.remainder(result, m); } // result < 2^63 again result += aLo * bHi; // aLo * bHi < 2^63, result < 2^64 result = times2ToThe32Mod(result, m); // result < m < 2^63 return plusMod(result, UnsignedLongs.remainder(aLo * bLo /* < 2^64 */, m), m); }
@GwtIncompatible // Too slow in GWT (~3min fully optimized) public void testDivideRemainderEuclideanProperty() { // Use a seed so that the test is deterministic: Random r = new Random(0L); for (int i = 0; i < 1000000; i++) { long dividend = r.nextLong(); long divisor = r.nextLong(); // Test that the Euclidean property is preserved: assertEquals( 0, dividend - (divisor * UnsignedLongs.divide(dividend, divisor) + UnsignedLongs.remainder(dividend, divisor))); } }
/** * Returns this modulo {@code val}. * * @since 14.0 */ @CheckReturnValue public UnsignedLong mod(UnsignedLong val) { return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value)); }
/** * Returns this modulo {@code val}. * * @since 14.0 */ @CheckReturnValue public UnsignedLong mod(UnsignedLong val) { return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value)); }
/** * Returns this modulo {@code val}. * * @since 14.0 */ @CheckReturnValue public UnsignedLong mod(UnsignedLong val) { return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value)); }
/** * Returns this modulo {@code val}. * * @since 14.0 */ public UnsignedLong mod(UnsignedLong val) { return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value)); }
private static long randomDivisor(long dividend) { long r = RANDOM_SOURCE.nextLong(); if (dividend == -1) { return r; } else { return UnsignedLongs.remainder(r, dividend + 1); } } }
@Benchmark long remainder(int reps) { long tmp = 0; for (int i = 0; i < reps; i++) { int j = i & ARRAY_MASK; tmp += UnsignedLongs.remainder(longs[j], divisors[j]); } return tmp; }