public Tuple <Polynomial, Polynomial, Polynomial> FindBezoutCoefficients(Polynomial firstArg, Polynomial secondArg) { var polyMath = new PolynomialMath(-1); Polynomial u0 = new Polynomial(new BigInteger[] { 1 }); Polynomial u1 = new Polynomial(new BigInteger[] { 0 }); Polynomial v0 = new Polynomial(new BigInteger[] { 0 }); Polynomial v1 = new Polynomial(new BigInteger[] { 1 }); Polynomial u2, v2, q0, r2; Polynomial r0 = firstArg; Polynomial r1 = secondArg; while (r1.Deg != -1) { q0 = polyMath.Div(r0, r1); u2 = polyMath.Sub(u0, polyMath.Mul(q0, u1)); v2 = polyMath.Sub(v0, polyMath.Mul(q0, v1)); r2 = polyMath.Add(polyMath.Mul(u2, firstArg), polyMath.Mul(v2, secondArg)); r0 = r1; r1 = r2; u0 = u1; u1 = u2; v0 = v1; v1 = v2; } return(new Tuple <Polynomial, Polynomial, Polynomial>(u0, v0, r0)); }
public List <long> FindRoots(Polynomial polynomial, long mod) { if (mod < 100) { var bruteForceMethod = new BruteforceRootFinder(); return(bruteForceMethod.FindRoots(polynomial, mod)); } var result = new List <long>(); var gcd = new PolynomialGcd(); var polyMath = new PolynomialMath(mod); var x = new Polynomial(new BigInteger[] { 0, 1 }); var powX = polyMath.ModPow(x, mod, polynomial); var h = polyMath.Sub(powX, x); var g = gcd.Calculate(polynomial, h, mod); if (g.Value(0) % mod == 0) { result.Add(0); g = polyMath.Div(g, new Polynomial(new BigInteger[] { 0, 1 })); } Roots(g, mod, result); return(result); }
void Roots(Polynomial polynomial, long mod, List <long> roots) { if (polynomial.Deg < 1) { return; } if (polynomial.Deg == 2) { if (mod % 2 == 0) { for (long i = 0; i < mod; i++) { if (polynomial.Value(i) % mod == 0) { roots.Add(i); } } } else { var a = polynomial[2]; var b = polynomial[1]; var c = polynomial[0]; var sqrt = new ModularSqrt(); var inverse = new ModularInverse(); var inv2A = inverse.Inverse(2 * a, mod); var tmp = inv2A * b; var root = sqrt.Sqrt(tmp * tmp - inverse.Inverse(a, mod) * c, mod); roots.Add((long)((-tmp + root) % mod)); roots.Add((long)((-tmp - root) % mod)); } return; } if (polynomial.Deg == 1) { var lc = (polynomial[1] + mod) % mod; if (lc == 1) { roots.Add((long)(-polynomial[0])); } else if (lc == mod - 1) { roots.Add((long)(polynomial[0])); } else { var inverse = new ModularInverse(); roots.Add((long)(-polynomial[0] * inverse.Inverse(polynomial[1], mod))); } return; } var polyMath = new PolynomialMath(mod); var arr = new BigInteger[2]; arr[0] = _random.Next() % mod; arr[1] = 1; var h = new Polynomial(arr); h = polyMath.ModPow(h, (mod - 1) / 2, polynomial); h[0] = h[0] - 1; var gcd = new PolynomialGcd(); var g = gcd.Calculate(polynomial, h, mod); while (g.Deg == 0 || g == h) { arr[0] = _random.Next() % mod; h = new Polynomial(arr); h = polyMath.ModPow(h, (mod - 1) / 2, polynomial); h[0] -= 1; g = gcd.Calculate(polynomial, h, mod); } Roots(g, mod, roots); Roots(polyMath.Div(polynomial, g), mod, roots); }