Ejemplo n.º 1
0
 protected internal new void Init()
 {
     if (Denominator.Value < 0)
     {
         Numerator   = new IntegerNumber(-Numerator.Value);
         Denominator = new IntegerNumber(-Denominator.Value);
     }
     if (!EDecimalWrapper.IsEqual(Denominator.Value, 0))
     {
         this.Value = CtxDivide((EDecimal)Numerator.Value, (EDecimal)Denominator.Value);
     }
     else
     {
         if (EDecimalWrapper.IsEqual(Numerator.Value, 0))
         {
             State = UndefinedState.NAN;
         }
         else if (Numerator.Value > 0)
         {
             State = UndefinedState.POSITIVE_INFINITY;
         }
         else
         {
             State = UndefinedState.NEGATIVE_INFINITY;
         }
     }
     base.Init();
 }
Ejemplo n.º 2
0
            internal static bool TryPulling(TrigTable table, ComplexNumber arg, out Entity res)
            {
                if (arg.IsImaginary())
                {
                    res = null;
                    return(false);
                }
                // arg in [0; 2pi]
                var dArg = arg.Real.Value;

                EDecimal Remainder(EDecimal a, EDecimal divisor)
                => a.RemainderNoRoundAfterDivide(divisor, MathS.Settings.DecimalPrecisionContext);

                var twoPi = RealNumber.CtxMultiply(2, MathS.DecimalConst.pi);

                dArg = Remainder(
                    RealNumber.CtxAdd(       // (
                        Remainder(dArg       //     dArg
                                  ,          //     %
                                  twoPi)     //     2pi
                        ,                    //   +
                        twoPi                //   2pi
                        )                    // )
                    ,                        // %
                    twoPi                    // 2pi
                    );

                int begin = 0;
                int end   = table.Count - 1;

                while (end - begin > 1)
                {
                    var mid = (end + begin) / 2;
                    if (EDecimalWrapper.IsGreater(table[mid].arg, dArg))
                    {
                        begin = mid;
                    }
                    else
                    {
                        end = mid;
                    }
                    if (end >= table.Count)
                    {
                        res = null;
                        return(false);
                    }
                }

                for (var j = begin; j <= end; j++)
                {
                    if (Number.Functional.IsZero(table[j].arg - dArg))
                    {
                        res = table[j].res;
                        return(true);
                    }
                }
                res = null;
                return(false);
            }
Ejemplo n.º 3
0
            /// <summary>
            /// Performs so-called downcasting, an attempt to narrow a number's affiliation to a number set
            /// It attempts to cast ComplexNumber to RealNumber, RealNumber to RationalNumber, RationalNumber to IntegerNumber
            /// </summary>
            /// <param name="a">
            /// Number to downcast
            /// </param>
            /// <returns>
            /// Downcasted or kept Number
            /// </returns>
            public static Number Downcast(Number a)
            {
                if (!MathS.Settings.DowncastingEnabled)
                {
                    return(a);
                }
                var res = SuperSwitch(
                    num => (Result: num[0], Continue: false),
                    (num) =>
                {
                    if (!(a as RealNumber).IsDefinite())
                    {
                        return(Result: a, Continue: false);
                    }
                    var ratnum = num[0];
                    var gcd    = Utils.GCD(ratnum.Denominator.Value, ratnum.Numerator.Value);
                    ratnum     = new RationalNumber(
                        new IntegerNumber(ratnum.Numerator.Value / gcd),
                        new IntegerNumber(ratnum.Denominator.Value / gcd)
                        );
                    if (EDecimalWrapper.IsEqual(ratnum.Denominator.Value, 1))
                    {
                        return(Result: ratnum.Numerator, Continue: false);
                    }
                    else
                    {
                        return(Result: ratnum, Continue: false);
                    }
                },
                    (num) =>
                {
                    if (!(a as RealNumber).IsDefinite())
                    {
                        return(Result: a, Continue: false);
                    }
                    var realnum = num[0];

                    if (TryCastToInt(realnum.Value, out var intres))
                    {
                        return(Result: new IntegerNumber(intres), Continue: false);
                    }

                    var attempt = FindRational(realnum.Value, MathS.Settings.FloatToRationalIterCount);
                    if (attempt is null ||
                        Number.Abs(attempt.Numerator) > MathS.Settings.MaxAbsNumeratorOrDenominatorValue ||
                        Number.Abs(attempt.Denominator) > MathS.Settings.MaxAbsNumeratorOrDenominatorValue)
                    {
                        return(Result: realnum, Continue: false);
                    }
Ejemplo n.º 4
0
        /// <summary>
        /// if a number is A + B where A is integer and B is in [0; 1], it performs operations
        /// for A and B separately and then concatenates
        /// </summary>
        /// <param name="num"></param>
        /// <param name="N"></param>
        /// <returns></returns>
        internal static string ToBaseN(EDecimal num, int N)
        {
            if (N > ALPHABET_TOCHAR.Length)
            {
                throw new MathSException("N should be <= than " + ALPHABET_TOCHAR.Length);
            }
            string sign = EDecimalWrapper.IsLess(num, 0) ? "-" : "";

            num = num.Abs();
            var      intPart   = num.RoundToIntegerExact(FloorContext).ToEInteger();
            EDecimal floatPart = RealNumber.CtxSubtract(num, intPart);

            string rightPart = !EDecimalWrapper.IsEqual(floatPart, 0) ? "." + FloatToBaseN(floatPart, N) : "";
            string leftPart  = sign + IntToBaseN(intPart, N);

            return(leftPart + rightPart);
        }
        public static RealNumber operator /(RationalNumber a, RationalNumber b)
        {
            if (!Functional.BothAreEqual(a, b, HierarchyLevel.RATIONAL))
            {
                return(Number.OpDiv(a, b) as RationalNumber);
            }
            var num = CtxMultiply(a.Numerator, b.Denominator);
            var den = CtxMultiply(a.Denominator, b.Numerator);

            if (EDecimalWrapper.IsEqual(den, 0))
            {
                return(RealNumber.NaN());
            }
            else
            {
                return(Number.Functional.Downcast(new RationalNumber(num, den)) as RationalNumber);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Transforms a floating number, but this number should be in [0; 1]
        /// </summary>
        /// <param name="num"></param>
        /// <param name="N"></param>
        /// <returns></returns>
        internal static string FloatToBaseN(EDecimal num /*should be < 1*/, int N)
        {
            if (EDecimalWrapper.IsGreater(num, 1) || EDecimalWrapper.IsLess(num, 0))
            {
                throw new SysException("Error in FloatToBaseN");
            }
            string res = "";

            while (EDecimalWrapper.IsGreater(num, 0))
            {
                num = RealNumber.CtxMultiply(num, N);

                EInteger intPart = num.RoundToIntegerExact(FloorContext).ToEInteger();
                res += ALPHABET_TOCHAR[intPart.ToInt32Checked()];
                num -= intPart;
            }
            return(res);
        }
Ejemplo n.º 7
0
            /// <summary>
            /// If the difference between value & round(value) is zero (see Number.IsZero), we consider value as an integer
            /// </summary>
            /// <param name="value"></param>
            /// <param name="res"></param>
            /// <returns></returns>
            private static bool TryCastToInt(EDecimal value, out EInteger res)
            {
                res = null;
                if (!value.IsFinite)
                {
                    return(false);
                }
                var intPart = value.ToEInteger();
                var rest    = RealNumber.CtxSubtract(value, intPart);

                if (EDecimalWrapper.IsLess(rest.Abs(), MathS.Settings.PrecisionErrorZeroRange))
                {
                    res = intPart;
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
Ejemplo n.º 8
0
 public static RealNumber operator *(RealNumber a, RealNumber b)
 {
     if (!a.IsDefinite() || !b.IsDefinite())
     {
         return(UndefinedStateSuperSwitch.Switch(
                    () => new RealNumber(UndefinedState.POSITIVE_INFINITY),
                    () => new RealNumber(UndefinedState.POSITIVE_INFINITY),
                    () => new RealNumber(UndefinedState.NEGATIVE_INFINITY),
                    () => new RealNumber(UndefinedState.NEGATIVE_INFINITY),
                    () => EDecimalWrapper.IsGreater(b.Value, 0) ? new RealNumber(UndefinedState.POSITIVE_INFINITY) : new RealNumber(UndefinedState.NEGATIVE_INFINITY),
                    () => EDecimalWrapper.IsGreater(b.Value, 0) ? new RealNumber(UndefinedState.NEGATIVE_INFINITY) : new RealNumber(UndefinedState.POSITIVE_INFINITY),
                    () => EDecimalWrapper.IsGreater(a.Value, 0) ? new RealNumber(UndefinedState.POSITIVE_INFINITY) : new RealNumber(UndefinedState.NEGATIVE_INFINITY),
                    () => EDecimalWrapper.IsGreater(a.Value, 0) ? new RealNumber(UndefinedState.NEGATIVE_INFINITY) : new RealNumber(UndefinedState.POSITIVE_INFINITY),
                    a, b));
     }
     if (!Functional.BothAreEqual(a, b, HierarchyLevel.REAL))
     {
         return(Number.OpMul(a, b) as RealNumber);
     }
     return(Number.Functional.Downcast(new RealNumber(CtxMultiply(a.Value, b.Value))) as RealNumber);
 }
Ejemplo n.º 9
0
 internal static bool PullCos(ComplexNumber arg, out Entity res)
 {
     if (TryPulling(TableCos, arg, out res))
     {
         return(true);
     }
     if (TryPulling(TableCos, -1 * arg, out res))
     {
         return(true);
     }
     if (TryPulling(TableCos, arg * 2, out res))
     {
         res = MathS.Sqrt((1 + res) / 2);
         if (EDecimalWrapper.IsLess((Number.Cos(arg) as RealNumber).Value, 0))
         {
             res *= -1;
         }
         return(true);
     }
     return(false);
 }
Ejemplo n.º 10
0
 internal static bool PullSin(ComplexNumber arg, out Entity res)
 {
     if (TryPulling(TableSin, arg, out res))
     {
         return(true);
     }
     if (TryPulling(TableSin, (RealNumber)MathS.DecimalConst.pi - arg, out res))
     {
         return(true);
     }
     if (TryPulling(TableCos, arg * 2, out res))
     {
         res = MathS.Sqrt((1 - res) / 2);
         if (EDecimalWrapper.IsLess((Number.Sin(arg) as RealNumber).Value, 0))
         {
             res *= -1;
         }
         return(true);
     }
     return(false);
 }
Ejemplo n.º 11
0
 /// <summary>
 /// Checks whether a number is zero
 /// </summary>
 /// <param name="num"></param>
 /// <returns></returns>
 public static bool IsZero(EDecimal num)
 {
     return(EDecimalWrapper.IsLess(num.Abs(), MathS.Settings.PrecisionErrorZeroRange));
 }
Ejemplo n.º 12
0
        /// <summary>
        /// Divides one polynom over another one
        /// </summary>
        /// <param name="p"></param>
        /// <param name="q"></param>
        /// <returns></returns>
        internal static Entity DividePolynoms(Entity p, Entity q)
        {
            // ---> (x^0.6 + 2x^0.3 + 1) / (x^0.3 + 1)
            var replacementInfo = GatherAllPossiblePolynomials(p + q, replaceVars: true).replacementInfo;

            var originalP = p;
            var originalQ = q;

            // TODO remove extra copy
            p = p.DeepCopy();
            q = q.DeepCopy();

            foreach (var pair in replacementInfo)
            {
                FindAndReplace(ref p, pair.Value, new VariableEntity(PolyInfo.NewVarName(pair.Key)));
                FindAndReplace(ref q, pair.Value, new VariableEntity(PolyInfo.NewVarName(pair.Key)));
            }

            var monoinfoQ = GatherAllPossiblePolynomials(q.Expand(), replaceVars: false).monoInfo;
            var monoinfoP = GatherAllPossiblePolynomials(p.Expand(), replaceVars: false).monoInfo;

            string polyvar = null;

            // TODO use Linq to find polyvar
            // First attempt to find polynoms
            foreach (var pair in monoinfoQ)
            {
                if (pair.Value != null && monoinfoP.ContainsKey(pair.Key) && monoinfoP[pair.Key] != null)
                {
                    polyvar = pair.Key;
                    break;
                }
            }
            // cannot divide, return unchanged
            if (string.IsNullOrEmpty(polyvar))
            {
                return(originalP / originalQ);
            }

            var maxpowQ = monoinfoQ[polyvar].Keys.Max();
            var maxpowP = monoinfoP[polyvar].Keys.Max();
            var maxvalQ = monoinfoQ[polyvar][maxpowQ];
            var maxvalP = monoinfoP[polyvar][maxpowP];

            var result = new Dictionary <EDecimal, Entity>();

            // TODO: add case where all powers are non-positive
            // for now just return polynomials unchanged
            if (EDecimalWrapper.IsLess(maxpowP, maxpowQ))
            {
                return(originalP / originalQ);
            }

            // possibly very long process
            while (EDecimalWrapper.IsGreaterOrEqual(maxpowP, maxpowQ))
            {
                // KeyPair is ax^n with Key=n, Value=a
                EDecimal deltapow = maxpowP - maxpowQ;
                Entity   deltamul = maxvalP / maxvalQ;
                result[deltapow] = deltamul;

                foreach (var n in monoinfoQ[polyvar])
                {
                    // TODO: precision loss can happen here. MUST be fixed somehow
                    EDecimal newpow = deltapow + n.Key;
                    if (!monoinfoP[polyvar].ContainsKey(newpow))
                    {
                        monoinfoP[polyvar][newpow] = -deltamul * n.Value;
                    }
                    else
                    {
                        monoinfoP[polyvar][newpow] -= deltamul * n.Value;
                    }
                }
                if (monoinfoP[polyvar].ContainsKey(maxpowP))
                {
                    monoinfoP[polyvar].Remove(maxpowP);
                }
                if (monoinfoP[polyvar].Count == 0)
                {
                    break;
                }

                maxpowP = monoinfoP[polyvar].Keys.Max();
                maxvalP = monoinfoP[polyvar][maxpowP];
            }

            // check if all left in P is zero. If something left, division is impossible => return P / Q
            var Zero = new NumberEntity(0);

            foreach (var coef in monoinfoP[polyvar])
            {
                var simplified = coef.Value.Simplify();
                if (simplified != Zero)
                {
                    return(originalP / originalQ);
                }
            }

            Entity res = Number.Create(0);

            foreach (var pair in result)
            {
                res += pair.Value.Simplify(5) * MathS.Pow(new VariableEntity(polyvar), pair.Key);
            }
            // TODO: we know that variable is the same but with suffux '_r'. This foreach loop can be speeded-up
            while (replacementInfo.Any(rep => res.FindSubtree(new VariableEntity(PolyInfo.NewVarName(rep.Key))) != null))
            {
                foreach (var subst in replacementInfo)
                {
                    FindAndReplace(ref res, new VariableEntity(PolyInfo.NewVarName(subst.Key)), subst.Value);
                }
            }
            return(res);
        }