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()); }
public void TestInteger() { var actual = Rational.Create(3); Assert.IsType <Integer>(actual); Assert.Equal(Integer.Create(3), actual); }
public void TestWithUndefined7() { var a = Integer.Create(4); var b = Real.Create(0); Assert.Equal(Real.NaN, a / b); }
/// <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)); }
/// <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