internal static bool DivisibleBySomeLowPrime(Digits digits, int n) { if (n == 0 || (digits[0] & 1) == 0) { Debug.Assert(false, "untested code"); return(true); } for (int l = 0; l != LowPrimesProduct.Length; l++) { Digit product = LowPrimesProduct[l] , productInverse = Digit.TwoAdicInverse(product) , r = 0; for (int i = 0; i != n; i++) { Digit mulby; unchecked { r += digits[i]; if (r < digits[i]) { r -= product; } mulby = productInverse * r; Debug.Assert(mulby * product == r, "internal error"); } r = product - Digit2.Hi((UInt64)mulby * product); } if (Digit.OddGcd(r, product) != 1) { return(true); } } return(false); }
internal Modulus(Digits mod, int digitN, bool fromRight) { if (digitN == 0 || mod[digitN - 1] == 0) { throw new ArgumentException(); } _mod = mod; _digitN = digitN; _fromRight = fromRight; _one = new Digits(digitN); _multiplier1 = new Digits(digitN); _multiplier2 = new Digits(digitN); // this.mod.Set(this.mod, _digitN); _leftRecip = new Reciprocal(); Digits.DivPrecondition(mod, digitN, _leftRecip); Digit mod0inv = 0; if ((mod[0] & 1) != 0) { mod0inv = Digit.TwoAdicInverse(mod[0]); } _rightRecip = mod0inv; int digitN2 = (digitN + 1) / 2; Digits temp = new Digits(digitN + digitN2); if (!fromRight) { _algorithm = new MulAlgorithm(_MulFromLeft); int dividendN = digitN + digitN2; _scaleBitN = 0; for (int i = 0; i != dividendN; i++) { temp[i] = Digit.MaxValue; } temp[dividendN - 1] = Digit.MaxValue >> _leftRecip._shiftBitN; Digits q = new Digits(digitN2 + 1); Digits r = new Digits(digitN); Digits.Div(temp, dividendN, mod, digitN, _leftRecip, q, r); Debug.Assert(q[digitN2] == 1, "internal error"); Digits.Add(r, 1U, r, digitN); Digits.Sub(mod, r, r, digitN); } else { _algorithm = new MulAlgorithm(_MulFromRight); _scaleBitN = Digit.BitN * digitN; if (mod0inv == 0) { throw new ArgumentException(); } _multiplier2[0] = mod0inv; temp[digitN] = Digits.Mul(mod, mod0inv, temp, digitN); Debug.Assert(temp[0] == 1, "internal error"); for (int i = 1; i != digitN2; i++) { Digit mul = unchecked (0 - mod0inv * temp[i]); _multiplier2[i] = mul; temp[i + digitN] = Digits.Accumulate(mod, mul, temp + i, digitN); Debug.Assert(temp[i] == 0, "internal error"); } _multiplier1._Set(temp + digitN2, digitN); } _ToModular(new Digits(new Digit[] { 1 }), 1, _one); }