//*********************************************************************** // Fast calculation of modular reduction using Barrett's reduction. // Requires x < b^(2k), where b is the base. In this case, base is // 2^32 (uint). // // Reference [4] //*********************************************************************** private void BarrettReduction(ref BigInteger x1, BigInteger x2, BigInteger n, BigInteger constant, ref BigInteger temp) { Multiply(x1, x2, ref temp); int k = n.Length, kPlusOne = k + 1, kMinusOne = k - 1; //var q1 = new BigInteger(0); //// q1 = x / b^(k-1) //for (int i = kMinusOne, j = 0; i < x.Length; i++, j++) // q1.Data[j] = x.Data[i]; //q1.Length = x.Length - kMinusOne; //if(q1.Length <= 0) // q1.Length = 1; //var q2 = q1 * constant; //q1.Recycle(); //q1 = q2; var q1 = new BigIntegerShell(temp, kMinusOne, temp.Length - kMinusOne) * constant; // r1 = x mod b^(k+1) // i.e. keep the lowest (k+1) words //var r1 = new BigInteger(0); //int lengthToCopy = (x.Length > kPlusOne) ? kPlusOne : x.Length; temp.Length = (temp.Length > kPlusOne) ? kPlusOne : temp.Length; //for(int i = 0; i < lengthToCopy; i++) // r1.Data[i] = x.Data[i]; //r1.Length = lengthToCopy; // r2 = (q3 * n) mod b^(k+1) // partial multiplication of q3 and n var r2 = new BigInteger(0); for (int i = kPlusOne; i < q1.Length; i++) { if (q1.Data[i] == 0) { continue; } ulong mcarry = 0; int t = i - kPlusOne; for (int j = 0; j < n.Length && t < kPlusOne; j++, t++) { // t = i + j ulong val = (q1.Data[i] * (ulong)n.Data[j]) + r2.Data[t] + mcarry; r2.Data[t] = (uint)val; mcarry = (val >> 32); } if (t < kPlusOne) { r2.Data[t] = (uint)mcarry; } } r2.Length = kPlusOne; while (r2.Length > 1 && r2.Data[r2.Length - 1] == 0) { r2.Length--; } temp.Subtract(r2); r2.Recycle(); if ((temp.Data[maxLength - 1] & 0x80000000) != 0) // negative { ulong carry = 1; for (var i = kPlusOne; carry != 0 && i < maxLength; i++) { var sum = temp.Data[i] + carry; carry = sum >> 32; temp.Data[i] = (uint)sum; } } while (temp >= n) { temp.Subtract(n); } q1.Recycle(); q1 = temp; temp = x1; x1 = q1; }
//*********************************************************************** // Fast calculation of modular reduction using Barrett's reduction. // Requires x < b^(2k), where b is the base. In this case, base is // 2^32 (uint). // // Reference [4] //*********************************************************************** private void BarrettReduction(ref BigInteger x1,BigInteger x2, BigInteger n, BigInteger constant,ref BigInteger temp) { Multiply(x1, x2, ref temp); int k = n.Length, kPlusOne = k+1, kMinusOne = k-1; //var q1 = new BigInteger(0); //// q1 = x / b^(k-1) //for (int i = kMinusOne, j = 0; i < x.Length; i++, j++) // q1.Data[j] = x.Data[i]; //q1.Length = x.Length - kMinusOne; //if(q1.Length <= 0) // q1.Length = 1; //var q2 = q1 * constant; //q1.Recycle(); //q1 = q2; var q1 = new BigIntegerShell(temp, kMinusOne, temp.Length - kMinusOne) * constant; // r1 = x mod b^(k+1) // i.e. keep the lowest (k+1) words //var r1 = new BigInteger(0); //int lengthToCopy = (x.Length > kPlusOne) ? kPlusOne : x.Length; temp.Length = (temp.Length > kPlusOne) ? kPlusOne : temp.Length; //for(int i = 0; i < lengthToCopy; i++) // r1.Data[i] = x.Data[i]; //r1.Length = lengthToCopy; // r2 = (q3 * n) mod b^(k+1) // partial multiplication of q3 and n var r2 = new BigInteger(0); for (int i = kPlusOne; i < q1.Length; i++) { if(q1.Data[i] == 0) continue; ulong mcarry = 0; int t = i - kPlusOne; for(int j = 0; j < n.Length && t < kPlusOne; j++, t++) { // t = i + j ulong val = (q1.Data[i] * (ulong)n.Data[j]) + r2.Data[t] + mcarry; r2.Data[t] = (uint)val; mcarry = (val >> 32); } if(t < kPlusOne) r2.Data[t] = (uint)mcarry; } r2.Length = kPlusOne; while(r2.Length > 1 && r2.Data[r2.Length-1] == 0) r2.Length--; temp.Subtract(r2); r2.Recycle(); if ((temp.Data[maxLength - 1] & 0x80000000) != 0) // negative { ulong carry = 1; for (var i = kPlusOne; carry != 0 && i<maxLength; i++) { var sum = temp.Data[i] + carry; carry = sum >> 32; temp.Data[i] = (uint)sum; } } while (temp >= n) temp.Subtract(n); q1.Recycle(); q1 = temp; temp = x1; x1 = q1; }