示例#1
0
        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);
            }
        }
示例#2
0
        //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);
        }
示例#3
0
        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);
        }
示例#4
0
        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);
                            }
                        }
                    }
                }
            }
        }
示例#5
0
        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);
            }
        }