//*********************************************************************** // Modulo Exponentiation //*********************************************************************** 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 var constant = new BigInteger(0); int i = n.Length << 1; constant.Data[i] = 0x00000001; constant.Length = i + 1; constant.Divide(n); //constant /= n; int totalBits = exp.bitCount(); int count = 0; var temp = new BigInteger(0); // perform squaring and multiply exponentiation for (var pos = 0; pos < exp.Length; pos++) { uint mask = 0x01; //Console.WriteLine("pos = " + pos); for (var index = 0; index < 32; index++) { if ((exp.Data[pos] & mask) != 0) { BarrettReduction(ref resultNum, tempNum, n, constant, ref temp); } mask <<= 1; BarrettReduction(ref tempNum, tempNum, n, constant, ref temp); if (tempNum.Length == 1 && tempNum.Data[0] == 1) { if (thisNegative && (exp.Data[0] & 0x1) != 0) //odd exp { resultNum.Negative(); } return(resultNum); } count++; if (count == totalBits) { break; } } } constant.Recycle(); temp.Recycle(); if (thisNegative && (exp.Data[0] & 0x1) != 0) //odd exp { resultNum.Negative(); } return(resultNum); }
public static void Multiply(BigInteger bi1, BigInteger bi2, ref BigInteger result) { const int lastPos = maxLength - 1; bool bi1Neg = false, bi2Neg = false; // take the absolute value of the inputs try { if ((bi1.Data[lastPos] & 0x80000000) != 0) // bi1 negative { bi1Neg = true; bi1 = -bi1; } if ((bi2.Data[lastPos] & 0x80000000) != 0) // bi2 negative { bi2Neg = true; bi2 = -bi2; } } catch (Exception) { } result.Clear(); // multiply the absolute values try { for (int i = 0; i < bi1.Length; i++) { if (bi1.Data[i] == 0) { continue; } ulong mcarry = 0; for (int j = 0, k = i; j < bi2.Length; j++, k++) { // k = i + j ulong val = ((ulong)bi1.Data[i] * (ulong)bi2.Data[j]) + (ulong)result.Data[k] + mcarry; result.Data[k] = (uint)val; mcarry = (val >> 32); } if (mcarry != 0) { result.Data[i + bi2.Length] = (uint)mcarry; } } } catch (Exception) { throw (new ArithmeticException("Multiplication overflow.")); } result.Length = bi1.Length + bi2.Length; if (result.Length > maxLength) { result.Length = maxLength; } while (result.Length > 1 && result.Data[result.Length - 1] == 0) { result.Length--; } // overflow check (result is -ve) if ((result.Data[lastPos] & 0x80000000) != 0) { if (bi1Neg != bi2Neg && result.Data[lastPos] == 0x80000000) // different sign { // handle the special case where multiplication produces // a max negative number in 2's complement. if (result.Length == 1) { return; } else { bool isMaxNeg = true; for (int i = 0; i < result.Length - 1 && isMaxNeg; i++) { if (result.Data[i] != 0) { isMaxNeg = false; } } if (isMaxNeg) { return; } } } throw (new ArithmeticException("Multiplication overflow.")); } // if input has different signs, then result is -ve if (bi1Neg != bi2Neg) { result.Negative(); } return; }
public static void Multiply(BigInteger bi1, BigInteger bi2,ref BigInteger result) { const int lastPos = maxLength - 1; bool bi1Neg = false, bi2Neg = false; // take the absolute value of the inputs try { if ((bi1.Data[lastPos] & 0x80000000) != 0) // bi1 negative { bi1Neg = true; bi1 = -bi1; } if ((bi2.Data[lastPos] & 0x80000000) != 0) // bi2 negative { bi2Neg = true; bi2 = -bi2; } } catch (Exception) { } result.Clear(); // multiply the absolute values try { for (int i = 0; i < bi1.Length; i++) { if (bi1.Data[i] == 0) continue; ulong mcarry = 0; for (int j = 0, k = i; j < bi2.Length; j++, k++) { // k = i + j ulong val = ((ulong)bi1.Data[i] * (ulong)bi2.Data[j]) + (ulong)result.Data[k] + mcarry; result.Data[k] = (uint)val; mcarry = (val >> 32); } if (mcarry != 0) result.Data[i + bi2.Length] = (uint)mcarry; } } catch (Exception) { throw (new ArithmeticException("Multiplication overflow.")); } result.Length = bi1.Length + bi2.Length; if (result.Length > maxLength) result.Length = maxLength; while (result.Length > 1 && result.Data[result.Length - 1] == 0) result.Length--; // overflow check (result is -ve) if ((result.Data[lastPos] & 0x80000000) != 0) { if (bi1Neg != bi2Neg && result.Data[lastPos] == 0x80000000) // different sign { // handle the special case where multiplication produces // a max negative number in 2's complement. if (result.Length == 1) return; else { bool isMaxNeg = true; for (int i = 0; i < result.Length - 1 && isMaxNeg; i++) { if (result.Data[i] != 0) isMaxNeg = false; } if (isMaxNeg) return; } } throw (new ArithmeticException("Multiplication overflow.")); } // if input has different signs, then result is -ve if (bi1Neg != bi2Neg) result.Negative(); return; }