/*
 * This file contains a copy of the method binaryGcd in the class java.math.MutableBigInteger.
 * The reason is, that binaryGcD is not public and we needed to call it from outside the java.math package.
 * There is no aim to violate any copyright.
 * 
 * 
 * BigIntAux.java
 *
 * Created on 5. January 2003, 11:26
 */

package eu.mihosoft.freerouting.datastructures;

import java.math.BigInteger;

/**
 *
 * Auxiliary functions with BigInteger Parameters

 * @author Alfons Wirtz
 */

public class BigIntAux
{
    /**
     * calculates the determinant of the vectors
     * (p_x_1, p_y_1) and (p_x_2, p_y_2)
     */
    public static final BigInteger determinant (BigInteger p_x_1, BigInteger p_y_1,
                              BigInteger p_x_2, BigInteger p_y_2)
    {
        BigInteger tmp1 = p_x_1.multiply(p_y_2);
        BigInteger tmp2 = p_x_2.multiply(p_y_1);
        return tmp1.subtract(tmp2);
    }


    /**
     * auxiliary function to implement addition and translation in the
     * classes RationalVector and RationalPoint
     */
    public static final BigInteger[] add_rational_coordinates(BigInteger[] p_first,
                                              BigInteger [] p_second)
    {
        BigInteger[] result = new BigInteger[3];
        if (p_first[2].equals(p_second[2]))
        // both rational numbers have the same denominator
        {
            result[2] = p_first[2];
            result[0] = p_first[0].add(p_second[0]);
            result[1] = p_first[1].add(p_second[1]);
        }
        else
        // multiply both denominators for the new denominator
        // to be on the save side:
        // taking the leat common multiple whould be optimal
        {
            result[2] = p_first[2].multiply(p_second[2]);
            BigInteger tmp_1 = p_first[0].multiply(p_second[2]);
            BigInteger tmp_2 = p_second[0].multiply(p_first[2]);
            result[0] = tmp_1.add(tmp_2);
            tmp_1 = p_first[1].multiply(p_second[2]);
            tmp_2 = p_second[1].multiply(p_first[2]);
            result[1] = tmp_1.add(tmp_2);
        }
        return result;
    }

    // the following function binaryGcd is copied from private parts of java.math
    // because we need it public.

    /*
     * trailingZeroTable[i] is the number of trailing zero bits in the binary
     * representaion of i.
     */
    final static byte trailingZeroTable[] = {
      -25, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};

    /**
     * Calculate GCD of a and b interpreted as unsigned integers.
     */
    public static final int binaryGcd(int a, int b) {
        if (b==0)
            return a;
        if (a==0)
            return b;

        int x;
        int aZeros = 0;
        while ((x = a & 0xff) == 0) {
            a >>>= 8;
            aZeros += 8;
        }
        int y = trailingZeroTable[x];
        aZeros += y;
        a >>>= y;

        int bZeros = 0;
        while ((x = b & 0xff) == 0) {
            b >>>= 8;
            bZeros += 8;
        }
        y = trailingZeroTable[x];
        bZeros += y;
        b >>>= y;

        int t = (aZeros < bZeros ? aZeros : bZeros);

        while (a != b) {
            if ((a+0x80000000) > (b+0x80000000)) {  // a > b as unsigned
                a -= b;

                while ((x = a & 0xff) == 0)
                    a >>>= 8;
                a >>>= trailingZeroTable[x];
            } else {
                b -= a;

                while ((x = b & 0xff) == 0)
                    b >>>= 8;
                b >>>= trailingZeroTable[x];
            }
        }
        return a<<t;
    }

    private BigIntAux() // disallow instantiation
    {
    }
}