public static long gcd()

in commons-numbers-core/src/main/java/org/apache/commons/numbers/core/ArithmeticUtils.java [141:192]


    public static long gcd(long p, long q) {
        // Perform the gcd algorithm on negative numbers, so that -2^63 does not
        // need to be handled separately
        long a = p > 0 ? -p : p;
        long b = q > 0 ? -q : q;

        long negatedGcd;
        if (a == 0) {
            negatedGcd = b;
        } else if (b == 0) {
            negatedGcd = a;
        } else {
            // Make "a" and "b" odd, keeping track of common power of 2.
            final int aTwos = Long.numberOfTrailingZeros(a);
            final int bTwos = Long.numberOfTrailingZeros(b);
            a >>= aTwos;
            b >>= bTwos;
            final int shift = Math.min(aTwos, bTwos);

            // "a" and "b" are negative and odd.
            // If a < b then "gdc(a, b)" is equal to "gcd(a - b, b)".
            // If a > b then "gcd(a, b)" is equal to "gcd(b - a, a)".
            // Hence, in the successive iterations:
            //  "a" becomes the negative absolute difference of the current values,
            //  "b" becomes that value of the two that is closer to zero.
            while (true) {
                final long delta = a - b;

                if (delta == 0) {
                    // This way of terminating the loop is intentionally different from the int gcd implementation.
                    // Benchmarking shows that testing for long inequality (a != b) is slow compared to
                    // testing the delta against zero. The same change on the int gcd reduces performance there,
                    // hence we have two variants of this loop.
                    break;
                }

                b = Math.max(a, b);
                a = delta > 0 ? -delta : delta;

                // Remove any power of 2 in "a" ("b" is guaranteed to be odd).
                a >>= Long.numberOfTrailingZeros(a);
            }

            // Recover the common power of 2.
            negatedGcd = a << shift;
        }
        if (negatedGcd == Long.MIN_VALUE) {
            throw new NumbersArithmeticException("overflow: gcd(%d, %d) is 2^63",
                    p, q);
        }
        return -negatedGcd;
    }