Here you can find the source of modMultiply(long a, long b, int m)
Parameter | Description |
---|---|
a | first value |
b | second value |
m | a modulus |
public static int modMultiply(long a, long b, int m)
//package com.java2s; //License from project: Open Source License public class Main { /**//from w ww . j ava 2s . c o m * Some methods return this value as indication that the answer doesn't exist or is undefined.<br> * For example, when mod = 0 in modular arithmetics, or when a number isn't a perfect power and * a function should return its base. * <p>This constant equals to {@code Integer.MIN_VALUE} because {@code Integer.MIN_VALUE} * can't be a base of any perfect power that fits in long. Proof:<ul> * <li>Base of perfect square is a positive number.</li> * <li>Integer.MIN_VALUE<sup>3</sup> = ((-2)<sup>31</sup>)<sup>3</sup> = (-2)<sup>93</sup> < (-2)<sup>63</sup> = Long.MIN_VALUE.</li> * <li>Higher powers would give higher values.</li></ul> * So no power greater than one can return base = {@code Integer.MIN_VALUE} for any long integer. * <p>Also, any modular arithmetic operation returns non-negative value, * so negative values can be used as error codes. * <p>Error codes are more desirable than throwing an exception when performance matters. */ public static final int NOT_FOUND = Integer.MIN_VALUE; /** * Modular multiplication.<br> * Returns ( a * b )( mod m ).<br> * Differs from ( a * b ) % m in that it always returns non-negative value and never overflows.<br> * If m = 0, {@link #NOT_FOUND} is returned. * @param a first value * @param b second value * @param m a modulus * @return ( a * b )( mod m ), or {@link #NOT_FOUND} if m = 0 */ public static int modMultiply(long a, long b, int m) { if (m <= 0) { if (m == 0) return NOT_FOUND; m = -m; } a %= m; b %= m; a = (a * b) % m; if (a < 0L) a += m; return (int) a; } /** * Modular multiplication.<br> * Returns ( a * b )( mod m ).<br> * Differs from ( a * b ) % m in that it always returns non-negative value and never overflows.<br> * If m = 0, {@link #NOT_FOUND} is returned. * @param a first value * @param b second value * @param m a modulus * @return ( a * b )( mod m ), or {@link #NOT_FOUND} if m = 0 */ public static long modMultiply(long a, long b, long m) { if (m <= 0L) { if (m == 0L) return NOT_FOUND; if (m == Long.MIN_VALUE) { a *= b; if (a < 0L) a += m; return a; } m = -m; } a %= m; b %= m; if (m <= Integer.MAX_VALUE) { // Safe simple multiplication available. a = (a * b) % m; if (a < 0L) a += m; return a; } if (a < 0L) a += m; if (b < 0L) b += m; // a = min( a, b ), b = max( a, b ) if (a > b) { long number = a; a = b; b = number; } // Corner cases of Schrage's method. if (a < 2L) return a * b; if (b == m - 1L) return m - a; // Safe simple multiplication available. if (Long.numberOfLeadingZeros(a) + Long.numberOfLeadingZeros(b) > 64) return (a * b) % m; // Schrage's method. // http://home.earthlink.net/~pfenerty/pi/schrages_method.html // http://objectmix.com/java/312426-extending-schrage-multiplication.html long quot = m / a; long rem = m - quot * a; if (rem < quot) { long number = b / quot; number = a * (b - quot * number) - rem * number; return number < 0L ? number + m : number; } // Bitwise multiplication. long leftTillOverflow; long number = 0L; while (a > 0L) { if ((a & 1L) == 1L) { leftTillOverflow = m - number; if (leftTillOverflow > b) number += b; else number = b - leftTillOverflow; } a >>= 1; leftTillOverflow = m - b; if (leftTillOverflow > b) b <<= 1; else b -= leftTillOverflow; } return number; } }