Esempio n. 1
0
        public void TestRationalDowncasting()
        {
            var frac21_10 = Rational.Create(21, 10);

            Assert.IsType <Rational>(frac21_10);
            Assert.Equal(frac21_10, frac21_10.EvalNumerical());
            Assert.Equal(frac21_10, frac21_10.Simplify().EvalNumerical());

            var squared = Entity.Number.Pow(frac21_10, 2);

            Assert.IsType <Rational>(squared);
            Assert.Equal(Rational.Create(441, 100), squared);
            Assert.Equal(squared, squared.EvalNumerical());
            Assert.Equal(squared, squared.Simplify().EvalNumerical());

            var cubed = Entity.Number.Pow(squared, Rational.Create(3, 2));

            Assert.IsType <Rational>(cubed);
            Assert.Equal(Rational.Create(9261, 1000), cubed);
            Assert.Equal(cubed, cubed.EvalNumerical());
            Assert.Equal(cubed, cubed.Simplify().EvalNumerical());

            var ten = cubed + Rational.Create(739, 1000);

            Assert.IsType <Integer>(ten);
            Assert.Equal(Integer.Create(10), ten);
            Assert.Equal(ten, ten.EvalNumerical());
            Assert.Equal(ten, ten.Simplify().EvalNumerical());
        }
Esempio n. 2
0
        public void TestInteger()
        {
            var actual = Rational.Create(3);

            Assert.IsType <Integer>(actual);
            Assert.Equal(Integer.Create(3), actual);
        }
Esempio n. 3
0
        public void TestWithUndefined7()
        {
            var a = Integer.Create(4);
            var b = Real.Create(0);

            Assert.Equal(Real.NaN, a / b);
        }
Esempio n. 4
0
        /// <summary>Solves ax^3 + bx^2 + cx + d</summary>
        /// <param name="a">Coefficient of x^3</param>
        /// <param name="b">Coefficient of x^2</param>
        /// <param name="c">Coefficient of x</param>
        /// <param name="d">Free coefficient</param>
        /// <returns>Set of roots</returns>
        internal static IEnumerable <Entity> SolveCubic(Entity a, Entity b, Entity c, Entity d)
        {
            // en: https://en.wikipedia.org/wiki/Cubic_equation
            // ru: https://ru.wikipedia.org/wiki/%D0%A4%D0%BE%D1%80%D0%BC%D1%83%D0%BB%D0%B0_%D0%9A%D0%B0%D1%80%D0%B4%D0%B0%D0%BD%D0%BE

            if (TreeAnalyzer.IsZero(d))
            {
                return(SolveQuadratic(a, b, c).Append(0));
            }
            if (TreeAnalyzer.IsZero(a))
            {
                return(SolveQuadratic(b, c, d));
            }

            var coeff = MathS.i * MathS.Sqrt(3) / 2;
            var u1    = Integer.Create(1);
            var u2    = Rational.Create(-1, 2) + coeff;
            var u3    = Rational.Create(-1, 2) - coeff;
            var D0    = MathS.Sqr(b) - 3 * a * c;
            var D1    = (2 * MathS.Pow(b, 3) - 9 * a * b * c + 27 * MathS.Sqr(a) * d).InnerSimplified;
            var C     = MathS.Pow((D1 + MathS.Sqrt(MathS.Sqr(D1) - 4 * MathS.Pow(D0, 3))) / 2, Rational.Create(1, 3));

            return(new[] { u1, u2, u3 }.Select(uk =>
                                               C.Evaled == 0 && D0.Evaled == 0 ? -(b + uk * C) / 3 / a : -(b + uk * C + D0 / C / uk) / 3 / a));
        }
Esempio n. 5
0
        /// <summary>Tries to solve as polynomial</summary>
        /// <param name="expr">Polynomial of an expression</param>
        /// <param name="subtree">
        /// The expression the polynomial of (e. g. cos(x)^2 + cos(x) + 1 is a polynomial of cos(x))
        /// </param>
        /// <returns>A finite <see cref="Set"/> if successful, <see langword="null"/> otherwise</returns>
        internal static IEnumerable <Entity>?SolveAsPolynomial(Entity expr, Variable subtree)
        {
            // Safely expand the expression
            // Here we find all terms
            var children = TreeAnalyzer.GatherLinearChildrenOverSumAndExpand(expr, entity => entity.ContainsNode(subtree));

            if (children is null)
            {
                return(null);
            }
            // // //

            // Check if all are like {1} * x^n & gather information about them
            var monomialsByPower = GatherMonomialInformation
                                   <EInteger, TreeAnalyzer.PrimitiveInteger>(children, subtree);

            if (monomialsByPower == null)
            {
                return(null); // meaning that the given equation is not polynomial
            }
            var res = ReduceCommonPower(ref monomialsByPower)
                ? new Entity[] { 0 } // x5 + x3 + x2 - common power is 2, one root is 0, then x3 + x + 1
                : Enumerable.Empty <Entity>();
            var powers   = monomialsByPower.Keys.ToList();
            var gcdPower = powers.Aggregate((accumulate, current) => accumulate.Gcd(current));

            // // //

            if (gcdPower.IsZero)
            {
                gcdPower = EInteger.One;
            }
            // Change all replacements, x6 + x3 + 1 => x2 + x + 1
            if (!gcdPower.Equals(EInteger.One))
            {
                for (int i = 0; i < powers.Count; i++)
                {
                    powers[i] /= gcdPower;
                }
                monomialsByPower = monomialsByPower.ToDictionary(pair => pair.Key / gcdPower, pair => pair.Value);
            }
            // // //

            MultithreadingFunctional.ExitIfCancelled();

            var gcdPowerRoots = GetAllRootsOf1(gcdPower);

            Entity GetMonomialByPower(EInteger power) =>
            monomialsByPower.TryGetValue(power, out var monomial) ? monomial.InnerSimplified : 0;

            powers.Sort();
            if (!powers.Last().CanFitInInt32())
            {
                return(null);
            }
            return((powers.Count, powers.Last().ToInt32Unchecked()) switch
            {
                (0, _) => null,
                (_, 0) => Enumerable.Empty <Entity>(),
                (> 2, > 4) => null, // So far, we can't solve equations of powers more than 4
                // By this moment we know for sure that expr's power is <= 4, that expr is not a monomial,
                // and that it consists of more than 2 monomials
                (1, _) => new Entity[] { 0 },
                (2, _) =>
                // Solve a x ^ n + b = 0 for x ^ n -> x ^ n = -b / a
                MathS.Pow(subtree, Integer.Create(powers[1]))
                .Invert((-1 * monomialsByPower[powers[0]] / monomialsByPower[powers[1]]).InnerSimplified, subtree),
                (_, 2) => SolveQuadratic(GetMonomialByPower(2), GetMonomialByPower(1), GetMonomialByPower(0)),
                (_, 3) => SolveCubic(GetMonomialByPower(3), GetMonomialByPower(2), GetMonomialByPower(1), GetMonomialByPower(0)),
                (_, 4) => SolveQuartic(GetMonomialByPower(4), GetMonomialByPower(3),
                                       GetMonomialByPower(2), GetMonomialByPower(1), GetMonomialByPower(0)),
                _ => null
            } is { } resConcat