static S64 FindFactor(S64 n, U32 seed) { // Pollard's rho algorithm. U64 n2 = (S64)n; for (; ; ) { if (n2 % 2 == 0) return 2; if (_prime((S64)n2)) return (S64)n2; U64 a = (U64)XorShift(&seed) << 32; a |= (U64)XorShift(&seed); U64 y = a % (n2 + 1); U64 c = (U64)XorShift(&seed) + 1; U64 m = (U64)XorShift(&seed) + 1; U64 g; U64 r = 1; U64 q = 1; U64 ys = 0; U64 x; U64 i; do { x = y; for (i = 0; i < r; i++) y = (ModMul(y, y, n2) + c) % n2; U64 k = 0; do { ys = y; U64 min_value = m < r - k ? m : r - k; for (i = 0; i < min_value; i++) { y = (ModMul(y, y, n2) + c) % n2; q = ModMul(q, x > y ? x - y : y - x, n2); } g = _gcd((S64)q, (S64)n2); k += m; } while (k < r && g <= 1); r *= 2; } while (g <= 1); if (g == n2) { do { ys = (ModMul(ys, ys, n2) + c) % n2; g = _gcd((S64)(x > ys ? x - ys : ys - x), (S64)n2); } while (g <= 1); } if (g == n2) seed++; else n2 = g; } }
static U64 ModPow(U64 value, U64 exponent, U64 modulus) { U64 w = 1; while (exponent > 0) { if ((exponent & 1) != 0) w = ModMul(w, value, modulus); value = ModMul(value, value, modulus); exponent >>= 1; } return w; }
/* Begin the complex ModInt functions */ void CmplxModMul(CmplxModInt *Prod, CmplxModInt *a, CmplxModInt *b) {CmplxModInt P; ModInt T1,T2; ModMul(&T1,&a->r,&b->r); ModMul(&T2,&a->i,&b->i); ModSub(&P.r,&T1,&T2); ModMul(&T1,&a->r,&b->i); ModMul(&T2,&a->i,&b->r); ModAdd(&P.i,&T1,&T2); *Prod=P; }
EXPORT S64 _modMul(S64 a, S64 b, S64 modulus) { THROWDBG(a < 0, 0xe9170006); THROWDBG(b < 0, 0xe9170006); THROWDBG(modulus < 0, 0xe9170006); return (S64)ModMul((U64)a, (U64)b, (U64)modulus); }
void ModPow(ModInt *Prod,ModInt *Base,ModInt *Expon) {ModInt b; b=*Base; while (!ModTestLowBit(Expon)) {ModMul(&b,&b,&b);RAW_ShiftR(Expon);} *Prod=b; RAW_ShiftR(Expon); while (!IsModZero(Expon)) { ModMul(&b,&b,&b); if (ModTestLowBit(Expon)) ModMul(Prod,Prod,&b); RAW_ShiftR(Expon); } }
void IModPow(ModInt *Prod,UINT32 base,UINT32 expon) /* Raise an integer to an integer power, returning a ModInt */ {ModInt b; if (expon==0) {ModSet(Prod,1);return;} ModSet(&b,base); while (!(expon&1)) { ModMul(&b,&b,&b); expon>>=1; } *Prod=b; while (expon>>=1) { ModMul(&b,&b,&b); if (expon&1) ModMul(Prod,Prod,&b); } }