void parabolic(BigInteger a, BigInteger b, BigInteger c, BigInteger d, BigInteger e, BigInteger f) { var g = BigIntegerExt.Gcd(a, c); c = (c / g).Abs().Sqrt(); if (b.Sign > 0 == a.Sign < 0) { c = -c; } a = (a / g).Abs().Sqrt(); var m = c * d - a * e; if (m.IsZero) { var u = MathExt2.DeriveQuadratic(a * g, d, a * f, true); if (u.Length > 0) { linearWithGcd(a, c, -u[0]); if (u.Length > 1 && u[0] != u[1]) { linearWithGcd(a, c, -u[1]); } } } else { parabolic2(a, -c, m, a * g, d, a * f); } }
//static methods static BigInteger computeFinite(BigInteger num, BigInteger denom, List <BigInteger> subQuotients) { var g = BigIntegerExt.Gcd(num, denom); if (g != BigInteger.One) { num /= g; denom /= g; } if (denom.Sign < 0) { num = -num; denom = -denom; } var t = num.Mod(denom); var quotient = (num - t) / denom; num = t; while (num.Sign > 0 && denom.Sign > 0) { denom = BigInteger.DivRem(denom, num, out t); subQuotients.Add(denom); denom = num; num = t; } return(quotient); }
void linearWithGcd(BigInteger d, BigInteger e, BigInteger f) { var g = BigIntegerExt.Gcd(d, e); if (!g.IsZero && g != BigInteger.One) { d /= g; e /= g; f /= g; } linear(d, e, f); }
void hyperbolic3(BigInteger a, BigInteger b, BigInteger c, BigInteger f, List <Expression <Func <BigInteger, BigInteger, BigInteger, BigInteger> >[]> explist, Func <Rational[], Rational[]>[] selectors) { if (explist.Count == 0) { return; } var funcList = explist.Select(exp => new[] { (exp[0] != null) ? exp[0].Compile() : null, (exp[1] != null) ? exp[1].Compile() : null }).ToList(); foreach (var sd in squareDivisor(f.Abs())) { var fnew = -f / (sd * sd); var g = BigIntegerExt.Gcd(a, fnew).Abs(); foreach (var d in new BigDivisor(g)) { foreach (var set in quadraticDivisor(a / d, b, c * d, fnew / d)) { foreach (var selector in selectors) { foreach (var rt in computeQuadratic(set[4], set[3], set[2], 1, (s1, s2) => selector(new[] { (set[0] * s1 + set[1] * s2) * sd, s1 * d * sd }))) { addQuadraticSolutions(rt[0], rt[1], explist, funcList); } } } } } }
void complexHyperbolic(BigInteger a, BigInteger b, BigInteger c, BigInteger d, BigInteger e, BigInteger f) { //refactor to form ax^2 + cy^2 + f = 0 var m = 4 * a; var ba = m * c - b * b; var bb = m * e - 2 * b * d; var bc = m * f - d * d; var c2 = BigIntegerExt.Gcd(ba, bb).Abs(); ba /= c2; bb /= c2; var a2 = ba; if ((bb % 2).IsZero) { bb /= 2; } else { c2 /= 4; ba *= 2; } m = 2 * a; var f2 = bc * a2 - c2 * bb * bb; //reduce & precheck var g = BigIntegerExt.Gcd(a2, c2); if (g != BigInteger.One) { BigInteger r; f2 = BigInteger.DivRem(f2, g, out r); if (!r.IsZero) { return; } a2 /= g; c2 /= g; } //declare var selectors = new Func <Rational[], Rational[]>[] { r => { var y0 = (r[1] - bb) / ba; return(new[] { (r[0] - y0 * b - d) / m, y0 }); }, r => { var y0 = (r[1] - bb) / ba; return(new[] { (-r[0] - y0 * b - d) / m, y0 }); }, r => { var y0 = (-r[1] - bb) / ba; return(new[] { (r[0] - y0 * b - d) / m, y0 }); }, r => { var y0 = (-r[1] - bb) / ba; return(new[] { (-r[0] - y0 * b - d) / m, y0 }); } }; var p = -4 * a2 * c2; var q = p.Sqrt(); if (f2.IsZero) { if (q * q == p) { a2 *= 2; var m2 = a2 * m; var q2 = a2 * d + a2 * b * bb; var set = new[] { Tuple.Create(m2, ba * (a2 * b + q), q2 + q * bb), Tuple.Create(m2, ba * (a2 * b - q), q2 - q * bb), Tuple.Create(-m2, ba * (a2 * b + q), q2 + q * bb), Tuple.Create(-m2, ba * (a2 * b - q), q2 - q * bb), Tuple.Create(m2, -ba * (a2 * b + q), q2 + q * bb), Tuple.Create(m2, -ba * (a2 * b - q), q2 - q * bb), Tuple.Create(-m2, -ba * (a2 * b + q), q2 + q * bb), Tuple.Create(-m2, -ba * (a2 * b - q), q2 - q * bb) }; foreach (var item in set.Distinct()) { linearWithGcd(item.Item1, item.Item2, item.Item3); } } else { addStaticSolution(selectors, BigInteger.Zero, BigInteger.Zero); } } else if (q * q == p) { hyperbolic2(a2 * 2, q, 4 * a2 * f2, q * 2, selectors); } else { hyperbolic3(a2, BigInteger.Zero, c2, f2, createFunction2(a, b, c, d, e), selectors); } }