import java.math.BigInteger;
import java.util.*;

public class Euclid {

	public static long gcd(long a, long b) {
		return b == 0 ? Math.abs(a) : gcd(b, a % b);
	}

	public static long gcd2(long a, long b) {
		while (b != 0) {
			long t = b;
			b = a % b;
			a = t;
		}
		return Math.abs(a);
	}

	public static long lcm(long a, long b) {
		return Math.abs(a / gcd(a, b) * b);
	}

	// returns { gcd(a,b), x, y } such that gcd(a,b) = a*x + b*y
	public static long[] euclid(long a, long b) {
		long x = 1, y = 0, x1 = 0, y1 = 1;
		// invariant: a=a*x+b*y, b=a*x1+b*y1
		while (b != 0) {
			long q = a / b;
			long _x1 = x1;
			long _y1 = y1;
			long _b = b;
			x1 = x - q * x1;
			y1 = y - q * y1;
			b = a - q * b;
			x = _x1;
			y = _y1;
			a = _b;
		}
		return a > 0 ? new long[]{a, x, y} : new long[]{-a, -x, -y};
	}

	public static long[] euclid2(long a, long b) {
		if (b == 0)
			return a > 0 ? new long[]{a, 1, 0} : new long[]{-a, -1, 0};
		long[] r = euclid2(b, a % b);
		return new long[]{r[0], r[2], r[1] - a / b * r[2]};
	}

	public static int mod(long a, int m) {
		int A = (int) (a % m);
		return A >= 0 ? A : A + m;
	}

	// precondition: m > 0 && gcd(a, m) = 1
	public static int modInverse(int a, int m) {
		a = mod(a, m);
		return a == 0 ? 0 : mod((1 - (long) modInverse(m % a, a) * m) / a, m);
	}

	// precondition: m > 0 && gcd(a, m) = 1
	public static int modInverse2(int a, int m) {
		return mod(euclid(a, m)[1], m);
	}

	// precondition: p is prime
	public static int[] generateInverse(int p) {
		int[] res = new int[p];
		res[1] = 1;
		for (int i = 2; i < p; ++i)
			res[i] = (p - (p / i) * res[p % i] % p) % p;
		return res;
	}

	// returns x ≡ a[i] (mod p[i]), where gcd(p[i], p[j]) == 1
	public static BigInteger garnerRestore(int[] a, int[] p) {
		int[] x = a.clone();
		for (int i = 0; i < x.length; ++i)
			for (int j = 0; j < i; ++j)
				x[i] = mod(BigInteger.valueOf(p[j]).modInverse(BigInteger.valueOf(p[i])).longValue() * (x[i] - x[j]), p[i]);
		BigInteger res = BigInteger.valueOf(x[0]);
		BigInteger m = BigInteger.ONE;
		for (int i = 1; i < x.length; i++) {
			m = m.multiply(BigInteger.valueOf(p[i - 1]));
			res = res.add(m.multiply(BigInteger.valueOf(x[i])));
		}
		return res;
	}

	// returns x ≡ a[i] (mod p[i]), where gcd(p[i], p[j]) == 1
	public static int simpleRestore(int[] a, int[] p) {
		int res = 0;
		for (int i = 0, m = 1; i < a.length; i++, m *= p[i])
			while (res % p[i] != a[i])
				res += m;
		return res;
	}

	// Usage example
	public static void main(String[] args) {
		Random rnd = new Random(1);
		for (int steps = 0; steps < 10000; steps++) {
			int a = rnd.nextInt(20) - 10;
			int b = rnd.nextInt(20) - 10;
			BigInteger xa = BigInteger.valueOf(a);
			BigInteger xb = BigInteger.valueOf(b);
			long gcd1 = gcd(a, b);
			long gcd2 = gcd2(a, b);
			long gcd = xa.gcd(xb).longValue();

			long[] euclid1 = euclid(a, b);
			long[] euclid2 = euclid2(a, b);

			int inv1 = 0;
			int inv2 = 0;
			int inv = 0;
			if (gcd == 1 && b > 0) {
				inv1 = modInverse(a, b);
				inv2 = modInverse2(a, b);
				inv = xa.modInverse(xb).intValue();
			}

			if (gcd1 != gcd || gcd2 != gcd || !Arrays.equals(euclid1, euclid2) || euclid1[0] != gcd || inv1 != inv
					|| inv2 != inv) {
				System.err.println(a + " " + b);
			}
		}
		long a = 6;
		long b = 9;
		long[] res = euclid(a, b);
		System.out.println(res[1] + " * (" + a + ") " + " + " + res[2] + " * (" + b + ") = gcd(" + a + "," + b + ") = "
				+ res[0]);

		System.out.println(Arrays.toString(generateInverse(7)));
	}
}
