Here you can find the source of modDivide(long a, long b, long m)
Parameter | Description |
---|---|
a | the dividend |
b | the divisor |
m | the modulus |
public static long[] modDivide(long a, long b, long m)
//package com.java2s; //License from project: Open Source License public class Main { /**// w ww .ja v a 2 s . 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 division. Returns a solution of equation ( x * b )( mod m ) = a. * <p>The solution has the form: x = x<sub>0</sub> + increment * k, where<ul> * <li>0 ≤ k < gcd, k is integer</li> * <li>increment = m / gcd</li> * <li>x<sub>0</sub> = a / gcd * {@link #modInverse}( b, m )</li> * <li>gcd = {@link #gcd}( b, m )</li></ul> * If a % gcd != 0 then the equation cannot be solved.<br> * The value returned is a tuple ( x<sub>0</sub>, increment, quantity ), * where quantity is the quantity of solutions, it equals to gcd. * If there's no solution, a tuple ( {@link #NOT_FOUND}, 0, 0 ) is returned. * <p>A simple loop to print all solutions (it handles situation when * solution[ 2 ] == Integer.MIN_VALUE - see section below):<br> * <code>int solution[] = modDivide( a, b, m );<br> * int x = solution[ 0 ];<br> * int increment = solution[ 1 ];<br> * for ( int k = -solution[ 2 ]; k < 0; k++ )<br> * {<br> * System.out.println( x );<br> * x += increment;<br> * }</code> * <p><b>Examples:</b><br><br> * <b>modDivide( 5, 3, 7 )</b><br> * modDivide( 5, 3, 7 ) = ( 5 / 3 )( mod 7 ) = ( 5 * ( 3<sup>-1</sup>( mod 7 ) ) )( mod 7 ) = ( 5 * 5 )( mod 7 ) = 4( mod 7 )<br> * <i>Check:</i> ( 4 * 3 )( mod 7 ) = 12( mod 7 ) = 5( mod 7 )<br> * <i>Returned value:</i> [ 4, 7, 1 ]<br><br> * <b>modDivide( 4, 2, 6 )</b><br> * gcd = gcd( 2, 6 ) = 2<br> * modDivide( 4 / gcd, 2 / gcd, 6 / gcd ) = modDivide( 2, 1, 3 ) = ( 2 * ( 1<sup>-1</sup>( mod 3 ) ) )( mod 3 ) = ( 2 * 1 )( mod 3 ) = 2( mod 3 )<br> * modDivide( 4, 2, 6 ) = ( 2 + 6 / gcd * k )( mod 6 ) = ( 2 + 3 * k )( mod 6 ), where 0 ≤ k < gcd = 2, so there are two solutions: 2 and 5<br> * <i>Check:</i> ( 2 * ( 2 + 3 * 0 ) )( mod 6 ) = ( 2 * 2 )( mod 6 ) = 4( mod 6 )<br> * <i>Check:</i> ( 2 * ( 2 + 3 * 1 ) )( mod 6 ) = ( 2 * 5 )( mod 6 ) = 4( mod 6 )<br> * <i>Returned value:</i> [ 2, 3, 2 ] * <p>About Integer.MIN_VALUE:<br> * First solution, increment and quantity are non-negative, except for special cases of MIN_VALUE.<ul> * <li>If b = 0 or MIN_VALUE and m = MIN_VALUE then solutions quantity (gcd) equals to MIN_VALUE (is negative).</li> * <li>If b ≠ 2<sup>k</sup> for any integer k and m = MIN_VALUE then solutions quantity (gcd) equals to 1 (one) and increment = MIN_VALUE.</li> * <li>First solution is never negative. {@link #NOT_FOUND} is used to indicate that the solution doesn't exist.</li></ul> * So increment = MIN_VALUE doesn't matter due to having only one solution (the increment won't be used). * The only exception situation is b = 0 or MIN_VALUE and m = MIN_VALUE leading to solutions quantity = MIN_VALUE. * @param a the dividend * @param b the divisor * @param m the modulus * @return a tuple ( first solution x<sub>0</sub>, increment, quantity ), * which produces a set of solutions of equation ( x * b )( mod m ) = a * in the form x = x<sub>0</sub> + increment * k, where k is integer, 0 ≤ k < quantity.<br> * If there's no solution, a tuple ( {@link #NOT_FOUND}, 0, 0 ) is returned. */ public static int[] modDivide(int a, int b, int m) { if (m == 0) return new int[] { NOT_FOUND, 0, 0 }; a %= m; // Extended GCD for b and m. int x = 0; int u = 1; int gcd = m; while (b != 0) { int q = gcd / b; int r = gcd - q * b; int n = x - u * q; gcd = b; b = r; x = u; u = n; } if (gcd < 0 && gcd > Integer.MIN_VALUE) { gcd = -gcd; x = -x; } // gcd = 0 if and only if b = 0 and m = 0. // m != 0 => gcd != 0. u = a / gcd; if (u * gcd == a) { m /= gcd; x = modMultiply(u, x, m); // x is the first solution, // m is the increment, // gcd is the quantity of solutions. if (m < 0) m = -m; return new int[] { x, m, gcd }; } return new int[] { NOT_FOUND, 0, 0 }; } /** * Modular division. Returns a solution of equation ( x * b )( mod m ) = a. * <p>The solution has the form: x = x<sub>0</sub> + increment * k, where<ul> * <li>0 ≤ k < gcd, k is integer</li> * <li>increment = m / gcd</li> * <li>x<sub>0</sub> = a / gcd * {@link #modInverse}( b, m )</li> * <li>gcd = {@link #gcd}( b, m )</li></ul> * If a % gcd != 0 then the equation cannot be solved.<br> * The value returned is a tuple ( x<sub>0</sub>, increment, quantity ), * where quantity is the quantity of solutions, it equals to gcd. * If there's no solution, a tuple ( {@link #NOT_FOUND}, 0, 0 ) is returned. * <p>A simple loop to print all solutions (it handles situation when * solution[ 2 ] == Long.MIN_VALUE - see section below):<br> * <code>long solution[] = modDivide( a, b, m );<br> * long x = solution[ 0 ];<br> * long increment = solution[ 1 ];<br> * for ( long k = -solution[ 2 ]; k < 0L; k++ )<br> * {<br> * System.out.println( x );<br> * x += increment;<br> * }</code> * <p><b>Examples:</b><br><br> * <b>modDivide( 5, 3, 7 )</b><br> * modDivide( 5, 3, 7 ) = ( 5 / 3 )( mod 7 ) = ( 5 * ( 3<sup>-1</sup>( mod 7 ) ) )( mod 7 ) = ( 5 * 5 )( mod 7 ) = 4( mod 7 )<br> * <i>Check:</i> ( 4 * 3 )( mod 7 ) = 12( mod 7 ) = 5( mod 7 )<br> * <i>Returned value:</i> [ 4, 7, 1 ]<br><br> * <b>modDivide( 4, 2, 6 )</b><br> * gcd = gcd( 2, 6 ) = 2<br> * modDivide( 4 / gcd, 2 / gcd, 6 / gcd ) = modDivide( 2, 1, 3 ) = ( 2 * ( 1<sup>-1</sup>( mod 3 ) ) )( mod 3 ) = ( 2 * 1 )( mod 3 ) = 2( mod 3 )<br> * modDivide( 4, 2, 6 ) = ( 2 + 6 / gcd * k )( mod 6 ) = ( 2 + 3 * k )( mod 6 ), where 0 ≤ k < gcd = 2, so there are two solutions: 2 and 5<br> * <i>Check:</i> ( 2 * ( 2 + 3 * 0 ) )( mod 6 ) = ( 2 * 2 )( mod 6 ) = 4( mod 6 )<br> * <i>Check:</i> ( 2 * ( 2 + 3 * 1 ) )( mod 6 ) = ( 2 * 5 )( mod 6 ) = 4( mod 6 )<br> * <i>Returned value:</i> [ 2, 3, 2 ] * <p>About Long.MIN_VALUE:<br> * First solution, increment and quantity are non-negative, except for special cases of MIN_VALUE.<ul> * <li>If b = 0 or MIN_VALUE and m = MIN_VALUE then solutions quantity (gcd) equals to MIN_VALUE (is negative).</li> * <li>If b ≠ 2<sup>k</sup> for any integer k and m = MIN_VALUE then solutions quantity (gcd) equals to 1 (one) and increment = MIN_VALUE.</li> * <li>First solution is never negative. {@link #NOT_FOUND} is used to indicate that the solution doesn't exist.</li></ul> * So increment = MIN_VALUE doesn't matter due to having only one solution (the increment won't be used). * The only exception situation is b = 0 or MIN_VALUE and m = MIN_VALUE leading to solutions quantity = MIN_VALUE. * @param a the dividend * @param b the divisor * @param m the modulus * @return a tuple ( first solution x<sub>0</sub>, increment, quantity ), * which produces a set of solutions of equation ( x * b )( mod m ) = a * in the form x = x<sub>0</sub> + increment * k, where k is integer, 0 ≤ k < quantity.<br> * If there's no solution, a tuple ( {@link #NOT_FOUND}, 0, 0 ) is returned. */ public static long[] modDivide(long a, long b, long m) { if (Integer.MIN_VALUE < m && m <= Integer.MAX_VALUE) { if (m == 0L) return new long[] { NOT_FOUND, 0L, 0L }; int ret[] = modDivide((int) (a % m), (int) (b % m), (int) m); return new long[] { ret[0], ret[1], ret[2] }; } a %= m; // Extended GCD for b and m. long x = 0L; long u = 1L; long gcd = m; while (b != 0L) { long q = gcd / b; long r = gcd - q * b; long n = x - u * q; gcd = b; b = r; x = u; u = n; } if (gcd < 0L && gcd > Long.MIN_VALUE) { gcd = -gcd; x = -x; } // gcd = 0 if and only if b = 0 and m = 0. // m != 0 => gcd != 0. u = a / gcd; if (u * gcd == a) { m /= gcd; x = modMultiply(u, x, m); // x is the first solution, // m is the increment, // gcd is the quantity of solutions. if (m < 0L) m = -m; return new long[] { x, m, gcd }; } return new long[] { NOT_FOUND, 0L, 0L }; } /** * 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; } }