public BigInteger modPow(BigInteger exp, BigInteger n)
{
if ((exp.data[maxLength - 1] & 0x80000000) != 0)
throw (new ArithmeticException("Positive exponents only."));
BigInteger resultNum = 1;
BigInteger tempNum;
bool thisNegative = false;
if ((this.data[maxLength - 1] & 0x80000000) != 0) // negative this
{
tempNum = -this % n;
thisNegative = true;
} else
tempNum = this % n; // ensures (tempNum * tempNum) < b^(2k)
if ((n.data[maxLength - 1] & 0x80000000) != 0) // negative n
n = -n;
// calculate constant = b^(2k) / m
BigInteger constant = new BigInteger();
int i = n.dataLength << 1;
constant.data[i] = 0x00000001;
constant.dataLength = i + 1;
constant = constant / n;
int totalBits = exp.bitCount();
int count = 0;
// perform squaring and multiply exponentiation
for (int pos = 0; pos < exp.dataLength; pos++) {
uint mask = 0x01;
//Console.WriteLine("pos = " + pos);
for (int index = 0; index < 32; index++) {
if ((exp.data[pos] & mask) != 0)
resultNum = BarrettReduction(resultNum * tempNum, n, constant);
mask <<= 1;
tempNum = BarrettReduction(tempNum * tempNum, n, constant);
if (tempNum.dataLength == 1 && tempNum.data[0] == 1) {
if (thisNegative && (exp.data[0] & 0x1) != 0) //odd exp
return -resultNum;
return resultNum;
}
count++;
if (count == totalBits)
break;
}
}
if (thisNegative && (exp.data[0] & 0x1) != 0) //odd exp
return -resultNum;
return resultNum;
}