static void Random(Digits mod, Digits arr, int n, Random generator) { Debug.Assert(!arr._Overlaps(mod), "overlapping arguments"); int sigDigitN = n; while (sigDigitN > 0 && mod[sigDigitN - 1] == 0) { Debug.Assert(false, "untested code"); arr[sigDigitN - 1] = 0; sigDigitN--; } if (sigDigitN == 0) { throw new ArgumentException(); } Digit nlead = mod[sigDigitN - 1]; int ntry = 0; do { ntry++; Debug.Assert(ntry <= 100, "too many iterations"); Digits.Random(arr, sigDigitN - 1, generator); arr[sigDigitN - 1] = Digit.Random(0, nlead, generator); } while (Digits.Compare(arr, mod, sigDigitN) >= 0); }
internal static Digits NewPrime(int pBitN, Random generator) { if (pBitN < Digit.BitN) { throw new ArgumentException(); } int pDigitN = (pBitN + (Digit.BitN - 1)) / Digit.BitN; Digits p = new Digits(pDigitN); while (true) { for ( int iteration = 0; iteration < _IterationsAllowed; iteration++ ) { Digits.Random(p, pDigitN, generator); p[pDigitN - 1] >>= Digit.BitN * pDigitN - pBitN; p[0] |= 1; Digits.SetBit(p, pBitN - 1, 1); Digits.SetBit(p, pBitN - 2, 1); if (DivisibleBySomeLowPrime(p, pDigitN)) { continue; } Modulus modulus = new Modulus(p, pDigitN, true); Digits minus1 = new Digits(pDigitN); Modular .Neg(modulus._one, minus1, modulus._mod, modulus._digitN); Digits exp = new Digits(pDigitN); Digits.Shift(p, -1, exp, pDigitN); Digits @base = new Digits(pDigitN); for (int i = 1; i <= _RabinTestN; i++) { if (i == 1) { Modular.Add(modulus._one , modulus._one , @base , modulus._mod , modulus._digitN); } else { Modular.NonZeroRandom( p, @base, pDigitN, generator); } Digits result = new Digits(pDigitN); modulus._Exp(@base, exp, pDigitN, result); if (Digits.Compare(result, minus1, pDigitN) == 0) { return(p); } if ( Digits.Compare(result, modulus._one, pDigitN) != 0 ) { break; } } } Debug.Assert(false, "too many iterations"); } }