public static int Jacobi(BigInteger a, BigInteger b)
{
// Jacobi defined only for odd integers
if ((b.data[0] & 0x1) == 0)
throw (new ArgumentException("Jacobi defined only for odd integers."));
if (a >= b) a %= b;
if (a.dataLength == 1 && a.data[0] == 0) return 0; // a == 0
if (a.dataLength == 1 && a.data[0] == 1) return 1; // a == 1
if (a < 0) {
if ((((b - 1).data[0]) & 0x2) == 0) //if( (((b-1) >> 1).data[0] & 0x1) == 0)
return Jacobi(-a, b);
else
return -Jacobi(-a, b);
}
int e = 0;
for (int index = 0; index < a.dataLength; index++) {
uint mask = 0x01;
for (int i = 0; i < 32; i++) {
if ((a.data[index] & mask) != 0) {
index = a.dataLength; // to break the outer loop
break;
}
mask <<= 1;
e++;
}
}
BigInteger a1 = a >> e;
int s = 1;
if ((e & 0x1) != 0 && ((b.data[0] & 0x7) == 3 || (b.data[0] & 0x7) == 5))
s = -1;
if ((b.data[0] & 0x3) == 3 && (a1.data[0] & 0x3) == 3)
s = -s;
if (a1.dataLength == 1 && a1.data[0] == 1)
return s;
else
return (s * Jacobi(b % a1, a1));
}