Java Long Number Mod modDivide(long a, long b, long m)

Here you can find the source of modDivide(long a, long b, long m)

Description

Modular division.

License

Open Source License

Parameter

Parameter Description
a the dividend
b the divisor
m the modulus

Return

a tuple ( first solution x0, increment, quantity ), which produces a set of solutions of equation ( x * b )( mod m ) = a in the form x = x0 + increment * k, where k is integer, 0 ≤ k < quantity.
If there's no solution, a tuple ( , 0, 0 ) is returned.

Declaration

public static long[] modDivide(long a, long b, long m) 

Method Source Code

//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> &lt; (-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 &le; k &lt; 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 &lt; 0; k++ )<br>
     * {<br>
     * &nbsp;&nbsp;&nbsp;&nbsp;System.out.println( x );<br>
     * &nbsp;&nbsp;&nbsp;&nbsp;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 &le; k &lt; 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 &ne; 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 &le; k &lt; 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 &le; k &lt; 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 &lt; 0L; k++ )<br>
     * {<br>
     * &nbsp;&nbsp;&nbsp;&nbsp;System.out.println( x );<br>
     * &nbsp;&nbsp;&nbsp;&nbsp;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 &le; k &lt; 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 &ne; 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 &le; k &lt; 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;
    }
}

Related

  1. mod(long a, long b)
  2. mod(long pNum, long pDivisor)
  3. mod(long v, long m)
  4. mod(long x, long y)
  5. modifiedCalcElementOffset(long index, long mask)
  6. modifyValue(long value, char op, long modifier, long max, long min)
  7. mods(long v, long m)
  8. modularReciprocal(long a, long mod)