Пример #1
0
        /// <summary>Analogy of <see cref="Math.Tan(double)"/></summary>
        public static EDecimal Tan(this EDecimal x, EContext context)
        {
            if (!x.IsFinite)
            {
                return(EDecimal.NaN);
            }
            var consts = ConstantCache.Lookup(context);
            var cos    = Cos(x, context);

            if (cos.IsZero)
            {
                return(EDecimal.NaN);
            }
            //calculate sin using cos
            var sin = CalculateSinFromCos(x, cos, consts, context);

            return(sin.Divide(cos, context));
        }
Пример #2
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);
        }
Пример #3
0
        /// <summary>Converts this value to a <c>decimal</c> under the Common
        /// Language Infrastructure (usually a.NET Framework decimal).
        /// Currently, converts this value to the precision and range of a.NET
        /// Framework decimal.</summary>
        /// <returns>A <c>decimal</c> under the Common Language Infrastructure
        /// (usually a.NET Framework decimal).</returns>
        public decimal ToDecimal()
        {
            ERational extendedNumber = this;

            if (extendedNumber.IsInfinity() || extendedNumber.IsNaN())
            {
                throw new OverflowException("This object's value is out of range");
            }
            try {
                EDecimal newDecimal = EDecimal.FromEInteger(extendedNumber.Numerator)
                                      .Divide(
                    EDecimal.FromEInteger(extendedNumber.Denominator),
                    EContext.CliDecimal.WithTraps(EContext.FlagOverflow));
                return((decimal)newDecimal);
            } catch (ETrapException ex) {
                throw new OverflowException("This object's value is out of range", ex);
            }
        }
Пример #4
0
        public (bool equal, Complex eval1, Complex eval2, Real err) AreEqual(Entity expr1, Entity expr2, Complex toSub)
        {
            foreach (var var in expr1.Vars)
            {
                expr1 = expr1.Substitute(var, toSub);
            }
            foreach (var var in expr2.Vars)
            {
                expr2 = expr2.Substitute(var, toSub);
            }
            var evaled1 = expr1.EvalNumerical();
            var evaled2 = expr2.EvalNumerical();

            return(
                evaled1 == evaled2 || /*non-finite goes with that*/
                (evaled1 - evaled2).Abs().EDecimal.CompareTo(EDecimal.FromDecimal(1e-20m)) < 0,

                evaled1, evaled2, (evaled1 - evaled2).Abs());
        }
Пример #5
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);
                }
            }
Пример #6
0
 public static void TestToDecimal()
 {
     try {
         EDecimal.FromString("8.8888888e-7").ToDecimal();
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     try {
         EDecimal.FromString("8.8888888e-8").ToDecimal();
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     try {
         EDecimal.FromString("8.8888888e-18").ToDecimal();
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
 }
Пример #7
0
        private void InitClass(EDecimal value, UndefinedState state)
        {
            Value = value;
            Type  = HierarchyLevel.REAL;
            State = state;
            switch (State)
            {
            case UndefinedState.NEGATIVE_INFINITY:
                Value = EDecimal.NegativeInfinity;
                break;

            case UndefinedState.POSITIVE_INFINITY:
                Value = EDecimal.PositiveInfinity;
                break;

            case UndefinedState.NAN:
                Value = 0;
                break;
            }
            Init();
        }
Пример #8
0
        public void TestDecimalString()
        {
            var fr = new RandomGenerator();

            for (var i = 0; i < 1000; ++i)
            {
                EDecimal ed = RandomObjects.RandomEDecimal(fr);
                if (!ed.IsFinite)
                {
                    continue;
                }
                decimal d;
                try {
                    System.Globalization.NumberStyles numstyles =
                        System.Globalization.NumberStyles.AllowExponent |
                        System.Globalization.NumberStyles.Number;
                    d = Decimal.Parse(
                        ed.ToString(),
                        numstyles,
                        System.Globalization.CultureInfo.InvariantCulture);
                    EDecimal ed3 = EDecimal.FromString(
                        ed.ToString(),
                        EContext.CliDecimal);
                    string msg = ed.ToString() + " (expanded: " +
                                 EDecimal.FromString(ed.ToString()) + ")";
                    TestCommon.CompareTestEqual(
                        (EDecimal)d,
                        ed3,
                        msg);
                } catch (OverflowException ex) {
                    EDecimal ed2 = EDecimal.FromString(
                        ed.ToString(),
                        EContext.CliDecimal);
                    Assert.IsTrue(
                        ed2.IsInfinity(),
                        ed.ToString(),
                        ex.ToString());
                }
            }
        }
Пример #9
0
        public bool SquareRootButton()
        {
            this.equalsPressed = false;
            if (IsError(this.text))
            {
                return(false);
            }
            var op = EDecimal.FromString(this.text, this.context);

            op = op.Sqrt(this.context);
            if (this.currentOperand == 0)
            {
                this.operand1 = op;
            }
            else
            {
                this.operand2 = op;
            }
            this.SetText(this.operand1);
            this.buffer.Clear();
            return(true);
        }
Пример #10
0
        internal static CBORObject ConvertToDecimalFrac(
            CBORObject o,
            bool isDecimal,
            bool extended)
        {
            if (o.Type != CBORType.Array)
            {
                throw new CBORException("Big fraction must be an array");
            }
            if (o.Count != 2)
            {
                throw new CBORException("Big fraction requires exactly 2 items");
            }
            if (!o[0].IsIntegral)
            {
                throw new CBORException("Exponent is not an integer");
            }
            if (!o[1].IsIntegral)
            {
                throw new CBORException("Mantissa is not an integer");
            }
            EInteger exponent = o[0].AsEInteger();
            EInteger mantissa = o[1].AsEInteger();

            if (exponent.GetSignedBitLength() > 64 && !extended)
            {
                throw new CBORException("Exponent is too big");
            }
            if (exponent.IsZero)
            {
                // Exponent is 0, so return mantissa instead
                return(CBORObject.FromObject(mantissa));
            }
            // NOTE: Discards tags. See comment in CBORTag2.
            return(isDecimal ?
                   CBORObject.FromObject(EDecimal.Create(mantissa, exponent)) :
                   CBORObject.FromObject(EFloat.Create(mantissa, exponent)));
        }
Пример #11
0
 public DateTime FromCBORObject(CBORObject obj)
 {
     if (obj.HasMostOuterTag(0))
     {
         return(StringToDateTime(obj.AsString()));
     }
     else if (obj.HasMostOuterTag(1))
     {
         if (!obj.IsFinite)
         {
             throw new CBORException("Not a finite number");
         }
         EDecimal dec          = obj.AsEDecimal();
         var      lesserFields = new int[7];
         var      year         = new EInteger[1];
         CBORUtilities.BreakDownSecondsSinceEpoch(
             dec,
             year,
             lesserFields);
         return(PropertyMap.BuildUpDateTime(year[0], lesserFields));
     }
     throw new CBORException("Not tag 0 or 1");
 }
Пример #12
0
        public static EDecimal RandomEDecimal(RandomGenerator r)
        {
            if (r.UniformInt(100) == 0)
            {
                int x = r.UniformInt(3);
                if (x == 0)
                {
                    return(EDecimal.PositiveInfinity);
                }
                if (x == 1)
                {
                    return(EDecimal.NegativeInfinity);
                }
                if (x == 2)
                {
                    return(EDecimal.NaN);
                }
                // Signaling NaN currently not generated because
                // it doesn't round-trip as well
            }
            string str = RandomDecimalString(r);

            return(EDecimal.FromString(str));
        }
Пример #13
0
        public static CBORObject Divide(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }
            if (b == null)
            {
                throw new ArgumentNullException("b");
            }
            if (a.Type != CBORType.Number)
            {
                throw new ArgumentException("a.Type (" + a.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            if (b.Type != CBORType.Number)
            {
                throw new ArgumentException("b.Type (" + b.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            object objA  = a.ThisItem;
            object objB  = b.ThisItem;
            int    typeA = a.ItemType;
            int    typeB = b.ItemType;

            if (typeA == CBORObject.CBORObjectTypeInteger && typeB ==
                CBORObject.CBORObjectTypeInteger)
            {
                var valueA = (long)objA;
                var valueB = (long)objB;
                if (valueB == 0)
                {
                    return((valueA == 0) ? CBORObject.NaN : ((valueA < 0) ?
                                                             CBORObject.NegativeInfinity : CBORObject.PositiveInfinity));
                }
                if (valueA == Int64.MinValue && valueB == -1)
                {
                    return(CBORObject.FromObject(valueA).Negate());
                }
                long quo = valueA / valueB;
                long rem = valueA - (quo * valueB);
                return((rem == 0) ? CBORObject.FromObject(quo) :
                       CBORObject.FromObject(
                           ERational.Create(
                               (EInteger)valueA,
                               (EInteger)valueB)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedRational ||
                typeB == CBORObject.CBORObjectTypeExtendedRational)
            {
                ERational e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(e1.Divide(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedDecimal ||
                typeB == CBORObject.CBORObjectTypeExtendedDecimal)
            {
                EDecimal e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA);
                EDecimal e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB);
                if (e1.IsZero && e2.IsZero)
                {
                    return(CBORObject.NaN);
                }
                EDecimal eret = e1.Divide(e2, null);
                // If either operand is infinity or NaN, the result
                // is already exact. Likewise if the result is a finite number.
                if (!e1.IsFinite || !e2.IsFinite || eret.IsFinite)
                {
                    return(CBORObject.FromObject(eret));
                }
                ERational er1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational er2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(er1.Divide(er2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB ==
                CBORObject.CBORObjectTypeExtendedFloat ||
                typeA == CBORObject.CBORObjectTypeDouble || typeB ==
                CBORObject.CBORObjectTypeDouble ||
                typeA == CBORObject.CBORObjectTypeSingle || typeB ==
                CBORObject.CBORObjectTypeSingle)
            {
                EFloat e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA);
                EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB);
                if (e1.IsZero && e2.IsZero)
                {
                    return(CBORObject.NaN);
                }
                EFloat eret = e1.Divide(e2, null);
                // If either operand is infinity or NaN, the result
                // is already exact. Likewise if the result is a finite number.
                if (!e1.IsFinite || !e2.IsFinite || eret.IsFinite)
                {
                    return(CBORObject.FromObject(eret));
                }
                ERational er1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational er2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(er1.Divide(er2)));
            }
            else
            {
                EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA);
                EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB);
                if (b2.IsZero)
                {
                    return(b1.IsZero ? CBORObject.NaN : ((b1.Sign < 0) ?
                                                         CBORObject.NegativeInfinity : CBORObject.PositiveInfinity));
                }
                EInteger bigrem;
                EInteger bigquo;
                {
                    EInteger[] divrem = b1.DivRem(b2);
                    bigquo = divrem[0];
                    bigrem = divrem[1];
                }
                return(bigrem.IsZero ? CBORObject.FromObject(bigquo) :
                       CBORObject.FromObject(ERational.Create(b1, b2)));
            }
        }
Пример #14
0
        public static CBORObject Multiply(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }
            if (b == null)
            {
                throw new ArgumentNullException("b");
            }
            if (a.Type != CBORType.Number)
            {
                throw new ArgumentException("a.Type (" + a.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            if (b.Type != CBORType.Number)
            {
                throw new ArgumentException("b.Type (" + b.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            object objA  = a.ThisItem;
            object objB  = b.ThisItem;
            int    typeA = a.ItemType;
            int    typeB = b.ItemType;

            if (typeA == CBORObject.CBORObjectTypeInteger && typeB ==
                CBORObject.CBORObjectTypeInteger)
            {
                var  valueA = (long)objA;
                var  valueB = (long)objB;
                bool apos   = valueA > 0L;
                bool bpos   = valueB > 0L;
                if (
                    (apos && ((!bpos && (Int64.MinValue / valueA) > valueB) ||
                              (bpos && valueA > (Int64.MaxValue / valueB)))) ||
                    (!apos && ((!bpos && valueA != 0L &&
                                (Int64.MaxValue / valueA) > valueB) ||
                               (bpos && valueA < (Int64.MinValue / valueB)))))
                {
                    // would overflow, convert to EInteger
                    var bvalueA = (EInteger)valueA;
                    var bvalueB = (EInteger)valueB;
                    return(CBORObject.FromObject(bvalueA * (EInteger)bvalueB));
                }
                return(CBORObject.FromObject(valueA * valueB));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedRational ||
                typeB == CBORObject.CBORObjectTypeExtendedRational)
            {
                ERational e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(e1.Multiply(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedDecimal ||
                typeB == CBORObject.CBORObjectTypeExtendedDecimal)
            {
                EDecimal e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA);
                EDecimal e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB);
                return(CBORObject.FromObject(e1.Multiply(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB ==
                CBORObject.CBORObjectTypeExtendedFloat ||
                typeA == CBORObject.CBORObjectTypeDouble || typeB ==
                CBORObject.CBORObjectTypeDouble ||
                typeA == CBORObject.CBORObjectTypeSingle || typeB ==
                CBORObject.CBORObjectTypeSingle)
            {
                EFloat e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA);
                EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB);
                return(CBORObject.FromObject(e1.Multiply(e2)));
            }
            else
            {
                EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA);
                EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB);
                return(CBORObject.FromObject(b1 * (EInteger)b2));
            }
        }
Пример #15
0
        public void TestDecimalString()
        {
            var fr = new RandomGenerator();

            // var sw = new System.Diagnostics.Stopwatch();
            // var sw2 = new System.Diagnostics.Stopwatch();
            // var sw3 = new System.Diagnostics.Stopwatch();
            for (var i = 0; i < 10000; ++i)
            {
                if (i % 100 == 0)
                {
                    // Console.WriteLine(i + " sw=" +
                    // sw.ElapsedMilliseconds + ", " + (sw2.ElapsedMilliseconds) +
                    // ", " + (sw3.ElapsedMilliseconds));
                }
                // sw3.Start();
                EDecimal ed = RandomObjects.RandomEDecimal(fr);
                // sw3.Stop();
                // Reduce to Decimal128. Without this reduction,
                // Decimal.Parse would run significantly more slowly
                // on average for random
                // EDecimals than
                // EDecimal.FromString(CliDecimal) does.
                // Decimal128 covers all numbers representable
                // in a CliDecimal.
                ed = ed.RoundToPrecision(EContext.Decimal128);

                if (!ed.IsFinite)
                {
                    continue;
                }
                string  edString = ed.ToString();
                decimal d;
                try {
                    System.Globalization.NumberStyles numstyles =
                        System.Globalization.NumberStyles.AllowExponent |
                        System.Globalization.NumberStyles.Number;
                    // sw.Start();
                    d = Decimal.Parse(
                        edString,
                        numstyles,
                        System.Globalization.CultureInfo.InvariantCulture);
                    // sw.Stop();
                    // sw2.Start();
                    EDecimal ed3 = EDecimal.FromString(
                        edString,
                        EContext.CliDecimal);
                    // sw2.Stop();
                    var edd = (EDecimal)d;
                    if (!edd.Equals(ed3))
                    {
                        string msg = ed.ToString() + " (expanded: " +
                                     EDecimal.FromString(ed.ToString()) + ")";
                        TestCommon.CompareTestEqual(
                            (EDecimal)d,
                            ed3,
                            msg);
                    }
                    // sw3.Stop();
                } catch (OverflowException ex) {
                    EDecimal ed2 = EDecimal.FromString(
                        edString,
                        EContext.CliDecimal);
                    if (!ed2.IsInfinity())
                    {
                        Assert.Fail(edString + "\n" + ex.ToString());
                    }
                }
            }
        }
Пример #16
0
 public void TestToUintChecked()
 {
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.1").ToUInt16Checked());
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.4").ToUInt16Checked());
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.5").ToUInt16Checked());
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.6").ToUInt16Checked());
     try {
         EDecimal.FromString("-1.0").ToUInt16Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     try {
         EDecimal.FromString("-1.4").ToUInt16Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     try {
         EDecimal.FromString("-1.5").ToUInt16Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     try {
         EDecimal.FromString("-1.6").ToUInt16Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.1").ToUInt32Checked());
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.4").ToUInt32Checked());
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.5").ToUInt32Checked());
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.6").ToUInt32Checked());
     try {
         EDecimal.FromString("-1.0").ToUInt32Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     try {
         EDecimal.FromString("-1.4").ToUInt32Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     try {
         EDecimal.FromString("-1.5").ToUInt32Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     try {
         EDecimal.FromString("-1.6").ToUInt32Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.1").ToUInt64Checked());
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.4").ToUInt64Checked());
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.5").ToUInt64Checked());
     Assert.AreEqual((byte)0, EDecimal.FromString("-0.6").ToUInt64Checked());
     try {
         EDecimal.FromString("-1.0").ToUInt64Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     try {
         EDecimal.FromString("-1.4").ToUInt64Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     try {
         EDecimal.FromString("-1.5").ToUInt64Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
     try {
         EDecimal.FromString("-1.6").ToUInt64Checked();
         Assert.Fail("Should have failed");
     } catch (OverflowException) {
         // NOTE: Intentionally empty
     } catch (Exception ex) {
         Assert.Fail(ex.ToString());
         throw new InvalidOperationException(String.Empty, ex);
     }
 }
Пример #17
0
 internal static bool IsLessOrEqual(EDecimal a, EDecimal b)
 => IsLess(a, b) || IsEqual(a, b);
Пример #18
0
 internal static bool IsEqual(EDecimal a, EDecimal b)
 => a.CompareTo(b) == 0;
Пример #19
0
 internal static bool IsGreaterOrEqual(EDecimal a, EDecimal b)
 => IsGreater(a, b) || IsEqual(a, b);
Пример #20
0
 internal static bool IsGreater(EDecimal a, EDecimal b)
 => a.CompareTo(b) == 1;
Пример #21
0
 internal static bool IsLess(EDecimal a, EDecimal b)
 => a.CompareTo(b) == -1;
Пример #22
0
 /// <summary>Helper function for calculating sin(x) from cos(x)</summary>
 static EDecimal CalculateSinFromCos(EDecimal x, EDecimal cos, ConstantCache consts, EContext context)
 {
Пример #23
0
        internal static CBORObject ParseJSONNumber(
            string str,
            int offset,
            int count,
            JSONOptions options,
            int[] endOfNumber)
        {
            if (String.IsNullOrEmpty(str) || count <= 0)
            {
                return(null);
            }
            if (offset < 0 || offset > str.Length)
            {
                return(null);
            }
            if (count > str.Length || str.Length - offset < count)
            {
                return(null);
            }
            JSONOptions opt = options ?? DefaultOptions;
            bool        preserveNegativeZero = options.PreserveNegativeZero;

            JSONOptions.ConversionMode kind = options.NumberConversion;
            int endPos        = offset + count;
            int initialOffset = offset;
            var negative      = false;

            if (str[initialOffset] == '-')
            {
                ++offset;
                negative = true;
            }
            int numOffset              = offset;
            var haveDecimalPoint       = false;
            var haveDigits             = false;
            var haveDigitsAfterDecimal = false;
            var haveExponent           = false;
            int i = offset;
            var decimalPointPos = -1;
            // Check syntax
            int k = i;

            if (endPos - 1 > k && str[k] == '0' && str[k + 1] >= '0' &&
                str[k + 1] <= '9')
            {
                if (endOfNumber != null)
                {
                    endOfNumber[0] = k + 2;
                }
                return(null);
            }
            for (; k < endPos; ++k)
            {
                char c = str[k];
                if (c >= '0' && c <= '9')
                {
                    haveDigits              = true;
                    haveDigitsAfterDecimal |= haveDecimalPoint;
                }
                else if (c == '.')
                {
                    if (!haveDigits || haveDecimalPoint)
                    {
                        // no digits before the decimal point,
                        // or decimal point already seen
                        if (endOfNumber != null)
                        {
                            endOfNumber[0] = k;
                        }
                        return(null);
                    }
                    haveDecimalPoint = true;
                    decimalPointPos  = k;
                }
                else if (c == 'E' || c == 'e')
                {
                    ++k;
                    haveExponent = true;
                    break;
                }
                else
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                        // Check if character can validly appear after a JSON number
                        if (c != ',' && c != ']' && c != '}' &&
                            c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                        {
                            return(null);
                        }
                        else
                        {
                            endPos = k;
                            break;
                        }
                    }
                    return(null);
                }
            }
            if (!haveDigits || (haveDecimalPoint && !haveDigitsAfterDecimal))
            {
                if (endOfNumber != null)
                {
                    endOfNumber[0] = k;
                }
                return(null);
            }
            if (haveExponent)
            {
                haveDigits = false;
                if (k == endPos)
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                    }
                    return(null);
                }
                char c = str[k];
                if (c == '+' || c == '-')
                {
                    ++k;
                }
                for (; k < endPos; ++k)
                {
                    c = str[k];
                    if (c >= '0' && c <= '9')
                    {
                        haveDigits = true;
                    }
                    else if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                        // Check if character can validly appear after a JSON number
                        if (c != ',' && c != ']' && c != '}' &&
                            c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                        {
                            return(null);
                        }
                        else
                        {
                            endPos = k;
                            break;
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }
                if (!haveDigits)
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                    }
                    return(null);
                }
            }
            if (endOfNumber != null)
            {
                endOfNumber[0] = endPos;
            }
            if (!haveExponent && !haveDecimalPoint &&
                (endPos - numOffset) <= 16)
            {
                // Very common case of all-digit JSON number strings
                // less than 2^53 (with or without number sign)
                long v  = 0L;
                int  vi = numOffset;
                for (; vi < endPos; ++vi)
                {
                    v = (v * 10) + (int)(str[vi] - '0');
                }
                if ((v != 0 || !negative) && v < (1L << 53) - 1)
                {
                    if (negative)
                    {
                        v = -v;
                    }
                    if (kind == JSONOptions.ConversionMode.Double)
                    {
                        return(CBORObject.FromObject((double)v));
                    }
                    else if (kind == JSONOptions.ConversionMode.Decimal128)
                    {
                        return(CBORObject.FromObject(EDecimal.FromInt64(v)));
                    }
                    else
                    {
                        return(CBORObject.FromObject(v));
                    }
                }
            }
            if (kind == JSONOptions.ConversionMode.Full)
            {
                if (!haveDecimalPoint && !haveExponent)
                {
                    EInteger ei = EInteger.FromSubstring(str, initialOffset, endPos);
                    if (preserveNegativeZero && ei.IsZero && negative)
                    {
                        // TODO: In next major version, change to EDecimal.NegativeZero
                        return(CBORObject.FromFloatingPointBits(0x8000, 2));
                    }
                    return(CBORObject.FromObject(ei));
                }
                if (!haveExponent && haveDecimalPoint && (endPos - numOffset) <= 19)
                {
                    // No more than 18 digits plus one decimal point (which
                    // should fit a long)
                    long lv   = 0L;
                    int  expo = -(endPos - (decimalPointPos + 1));
                    int  vi   = numOffset;
                    for (; vi < decimalPointPos; ++vi)
                    {
                        lv = checked ((lv * 10) + (int)(str[vi] - '0'));
                    }
                    for (vi = decimalPointPos + 1; vi < endPos; ++vi)
                    {
                        lv = checked ((lv * 10) + (int)(str[vi] - '0'));
                    }
                    if (negative)
                    {
                        lv = -lv;
                    }
                    if (!negative || lv != 0)
                    {
                        CBORObject cbor = CBORObject.NewArray()
                                          .Add(expo).Add(lv);
                        return(CBORObject.FromObjectAndTag(cbor, 4));
                    }
                }
                EDecimal ed = EDecimal.FromString(
                    str,
                    initialOffset,
                    endPos - initialOffset);
                if (ed.IsZero && negative)
                {
                    if (preserveNegativeZero && ed.Exponent.IsZero)
                    {
                        // TODO: In next major version, use EDecimal
                        return(CBORObject.FromFloatingPointBits(0x8000, 2));
                    }
                    else if (!preserveNegativeZero)
                    {
                        ed = ed.Negate();
                    }
                }
                return(CBORObject.FromObject(ed));
            }
            else if (kind == JSONOptions.ConversionMode.Double)
            {
                double dbl = EFloat.FromString(
                    str,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Binary64).ToDouble();
                if (!preserveNegativeZero && dbl == 0.0)
                {
                    dbl = 0.0;
                }
                return(CBORObject.FromObject(dbl));
            }
            else if (kind == JSONOptions.ConversionMode.Decimal128)
            {
                EDecimal ed = EDecimal.FromString(
                    str,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Decimal128);
                if (!preserveNegativeZero && ed.IsNegative && ed.IsZero)
                {
                    ed = ed.Negate();
                }
                return(CBORObject.FromObject(ed));
            }
            else if (kind == JSONOptions.ConversionMode.IntOrFloatFromDouble)
            {
                double dbl = EFloat.FromString(
                    str,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Binary64).ToDouble();
                if (!Double.IsNaN(dbl) && dbl >= -9007199254740991.0 &&
                    dbl <= 9007199254740991.0 && Math.Floor(dbl) == dbl)
                {
                    var idbl = (long)dbl;
                    return(CBORObject.FromObject(idbl));
                }
                return(CBORObject.FromObject(dbl));
            }
            else if (kind == JSONOptions.ConversionMode.IntOrFloat)
            {
                EContext ctx = EContext.Binary64.WithBlankFlags();
                double   dbl = EFloat.FromString(
                    str,
                    initialOffset,
                    endPos - initialOffset,
                    ctx).ToDouble();
                if ((ctx.Flags & EContext.FlagInexact) != 0)
                {
                    // Inexact conversion to double, meaning that the string doesn't
                    // represent an integer in [-(2^53)+1, 2^53), which is representable
                    // exactly as double, so treat as ConversionMode.Double
                    if (!preserveNegativeZero && dbl == 0.0)
                    {
                        dbl = 0.0;
                    }
                    return(CBORObject.FromObject(dbl));
                }
                else
                {
                    // Exact conversion; treat as ConversionMode.IntToFloatFromDouble
                    if (!Double.IsNaN(dbl) && dbl >= -9007199254740991.0 &&
                        dbl <= 9007199254740991.0 && Math.Floor(dbl) == dbl)
                    {
                        var idbl = (long)dbl;
                        return(CBORObject.FromObject(idbl));
                    }
                    return(CBORObject.FromObject(dbl));
                }
            }
            else
            {
                throw new ArgumentException("Unsupported conversion kind.");
            }
        }
Пример #24
0
        public static CBORObject Remainder(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }
            if (b == null)
            {
                throw new ArgumentNullException("b");
            }
            if (a.Type != CBORType.Number)
            {
                throw new ArgumentException("a.Type (" + a.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            if (b.Type != CBORType.Number)
            {
                throw new ArgumentException("b.Type (" + b.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            object objA  = a.ThisItem;
            object objB  = b.ThisItem;
            int    typeA = a.ItemType;
            int    typeB = b.ItemType;

            if (typeA == CBORObject.CBORObjectTypeInteger && typeB ==
                CBORObject.CBORObjectTypeInteger)
            {
                var valueA = (long)objA;
                var valueB = (long)objB;
                return((valueA == Int64.MinValue && valueB == -1) ?
                       CBORObject.FromObject(0) : CBORObject.FromObject(valueA % valueB));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedRational ||
                typeB == CBORObject.CBORObjectTypeExtendedRational)
            {
                ERational e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(e1.Remainder(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedDecimal ||
                typeB == CBORObject.CBORObjectTypeExtendedDecimal)
            {
                EDecimal e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA);
                EDecimal e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB);
                return(CBORObject.FromObject(e1.Remainder(e2, null)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB ==
                CBORObject.CBORObjectTypeExtendedFloat ||
                typeA == CBORObject.CBORObjectTypeDouble || typeB ==
                CBORObject.CBORObjectTypeDouble ||
                typeA == CBORObject.CBORObjectTypeSingle || typeB ==
                CBORObject.CBORObjectTypeSingle)
            {
                EFloat e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA);
                EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB);
                return(CBORObject.FromObject(e1.Remainder(e2, null)));
            }
            else
            {
                EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA);
                EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB);
                return(CBORObject.FromObject(b1 % (EInteger)b2));
            }
        }
Пример #25
0
 public static bool LessThan(this EDecimal bigDecimalOne, EDecimal bigDecimalTwo) =>
 bigDecimalOne.CompareTo(bigDecimalTwo) < 0;
Пример #26
0
 public static bool GreaterThanOrEquals(this EDecimal bigDecimalOne, EDecimal bigDecimalTwo) =>
 bigDecimalOne.CompareTo(bigDecimalTwo) >= 0;
Пример #27
0
        public static CBORObject Subtract(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }
            if (b == null)
            {
                throw new ArgumentNullException("b");
            }
            if (a.Type != CBORType.Number)
            {
                throw new ArgumentException("a.Type (" + a.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            if (b.Type != CBORType.Number)
            {
                throw new ArgumentException("b.Type (" + b.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            object objA  = a.ThisItem;
            object objB  = b.ThisItem;
            int    typeA = a.ItemType;
            int    typeB = b.ItemType;

            if (typeA == CBORObject.CBORObjectTypeInteger && typeB ==
                CBORObject.CBORObjectTypeInteger)
            {
                var valueA = (long)objA;
                var valueB = (long)objB;
                if ((valueB < 0 && Int64.MaxValue + valueB < valueA) ||
                    (valueB > 0 && Int64.MinValue + valueB > valueA))
                {
                    // would overflow, convert to EInteger
                    return(CBORObject.FromObject(((EInteger)valueA) -
                                                 (EInteger)valueB));
                }
                return(CBORObject.FromObject(valueA - valueB));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedRational ||
                typeB == CBORObject.CBORObjectTypeExtendedRational)
            {
                ERational e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(e1.Subtract(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedDecimal ||
                typeB == CBORObject.CBORObjectTypeExtendedDecimal)
            {
                EDecimal e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA);
                EDecimal e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB);
                return(CBORObject.FromObject(e1.Subtract(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB ==
                CBORObject.CBORObjectTypeExtendedFloat ||
                typeA == CBORObject.CBORObjectTypeDouble || typeB ==
                CBORObject.CBORObjectTypeDouble ||
                typeA == CBORObject.CBORObjectTypeSingle || typeB ==
                CBORObject.CBORObjectTypeSingle)
            {
                EFloat e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA);
                EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB);
                return(CBORObject.FromObject(e1.Subtract(e2)));
            }
            else
            {
                EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA);
                EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB);
                return(CBORObject.FromObject(b1 - (EInteger)b2));
            }
        }
Пример #28
0
        internal static CBORObject ParseJSONNumber(
            string chars,
            int offset,
            int count,
            JSONOptions options,
            int[] endOfNumber)
        {
            if (chars == null || chars.Length == 0 || count <= 0)
            {
                return(null);
            }
            if (offset < 0 || offset > chars.Length)
            {
                return(null);
            }
            if (count > chars.Length || chars.Length - offset < count)
            {
                return(null);
            }
            JSONOptions opt = options ?? CBORDataUtilities.DefaultOptions;
            bool        preserveNegativeZero = options.PreserveNegativeZero;

            JSONOptions.ConversionMode kind = options.NumberConversion;
            int endPos        = offset + count;
            int initialOffset = offset;
            var negative      = false;

            if (chars[initialOffset] == '-')
            {
                ++offset;
                negative = true;
            }
            int numOffset              = offset;
            var haveDecimalPoint       = false;
            var haveDigits             = false;
            var haveDigitsAfterDecimal = false;
            var haveExponent           = false;
            int i = offset;
            var decimalPointPos = -1;
            // Check syntax
            int k = i;

            if (endPos - 1 > k && chars[k] == '0' && chars[k + 1] >= '0' &&
                chars[k + 1] <= '9')
            {
                if (endOfNumber != null)
                {
                    endOfNumber[0] = k + 2;
                }
                return(null);
            }
            for (; k < endPos; ++k)
            {
                char c = chars[k];
                if (c >= '0' && c <= '9')
                {
                    haveDigits              = true;
                    haveDigitsAfterDecimal |= haveDecimalPoint;
                }
                else if (c == '.')
                {
                    if (!haveDigits || haveDecimalPoint)
                    {
                        // no digits before the decimal point,
                        // or decimal point already seen
                        if (endOfNumber != null)
                        {
                            endOfNumber[0] = k;
                        }
                        return(null);
                    }
                    haveDecimalPoint = true;
                    decimalPointPos  = k;
                }
                else if (c == 'E' || c == 'e')
                {
                    ++k;
                    haveExponent = true;
                    break;
                }
                else
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                        // Check if character can validly appear after a JSON number
                        if (c != ',' && c != ']' && c != '}' &&
                            c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                        {
                            return(null);
                        }
                        else
                        {
                            endPos = k;
                            break;
                        }
                    }
                    return(null);
                }
            }
            if (!haveDigits || (haveDecimalPoint && !haveDigitsAfterDecimal))
            {
                if (endOfNumber != null)
                {
                    endOfNumber[0] = k;
                }
                return(null);
            }
            var exponentPos = -1;
            var negativeExp = false;

            if (haveExponent)
            {
                haveDigits = false;
                if (k == endPos)
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                    }
                    return(null);
                }
                char c = chars[k];
                if (c == '+')
                {
                    ++k;
                }
                else if (c == '-')
                {
                    negativeExp = true;
                    ++k;
                }
                for (; k < endPos; ++k)
                {
                    c = chars[k];
                    if (c >= '0' && c <= '9')
                    {
                        if (exponentPos < 0 && c != '0')
                        {
                            exponentPos = k;
                        }
                        haveDigits = true;
                    }
                    else if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                        // Check if character can validly appear after a JSON number
                        if (c != ',' && c != ']' && c != '}' &&
                            c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                        {
                            return(null);
                        }
                        else
                        {
                            endPos = k;
                            break;
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }
                if (!haveDigits)
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                    }
                    return(null);
                }
            }
            if (endOfNumber != null)
            {
                endOfNumber[0] = endPos;
            }
            if (exponentPos >= 0 && endPos - exponentPos > 20)
            {
                // Exponent too high for precision to overcome (which
                // has a length no bigger than Int32.MaxValue, which is 10 digits
                // long)
                if (negativeExp)
                {
                    // underflow
                    if (kind == JSONOptions.ConversionMode.Double ||
                        kind == JSONOptions.ConversionMode.IntOrFloat)
                    {
                        if (!negative)
                        {
                            return(CBORObject.FromFloatingPointBits(0, 2));
                        }
                        else
                        {
                            return(CBORObject.FromFloatingPointBits(0x8000, 2));
                        }
                    }
                    else if (kind ==
                             JSONOptions.ConversionMode.IntOrFloatFromDouble)
                    {
                        return(CBORObject.FromObject(0));
                    }
                }
                else
                {
                    // overflow
                    if (kind == JSONOptions.ConversionMode.Double ||
                        kind == JSONOptions.ConversionMode.IntOrFloatFromDouble ||
                        kind == JSONOptions.ConversionMode.IntOrFloat)
                    {
                        return(CBORObject.FromFloatingPointBits(
                                   negative ? DoubleNegInfinity : DoublePosInfinity,
                                   8));
                    }
                    else if (kind == JSONOptions.ConversionMode.Decimal128)
                    {
                        return(CBORObject.FromObject(negative ?
                                                     EDecimal.NegativeInfinity : EDecimal.PositiveInfinity));
                    }
                }
            }
            if (!haveExponent && !haveDecimalPoint &&
                (endPos - numOffset) <= 16)
            {
                // Very common case of all-digit JSON number strings
                // less than 2^53 (with or without number sign)
                long v  = 0L;
                int  vi = numOffset;
                for (; vi < endPos; ++vi)
                {
                    v = (v * 10) + (int)(chars[vi] - '0');
                }
                if ((v != 0 || !negative) && v < (1L << 53) - 1)
                {
                    if (negative)
                    {
                        v = -v;
                    }
                    if (kind == JSONOptions.ConversionMode.Double)
                    {
                        return(CBORObject.FromFloatingPointBits(EFloat.FromInt64(v).ToDoubleBits(), 8));
                    }
                    else if (kind == JSONOptions.ConversionMode.Decimal128)
                    {
                        return(CBORObject.FromObject(EDecimal.FromInt64(v)));
                    }
                    else
                    {
                        return(CBORObject.FromObject(v));
                    }
                }
            }
            if (kind == JSONOptions.ConversionMode.Full)
            {
                if (!haveDecimalPoint && !haveExponent)
                {
                    EInteger ei = EInteger.FromSubstring(chars, initialOffset, endPos);
                    if (preserveNegativeZero && ei.IsZero && negative)
                    {
                        // TODO: In next major version, change to EDecimal.NegativeZero
                        return(CBORObject.FromFloatingPointBits(0x8000, 2));
                    }
                    return(CBORObject.FromObject(ei));
                }
                if (!haveExponent && haveDecimalPoint)
                {
                    // No more than 18 digits plus one decimal point (which
                    // should fit a long)
                    long lv         = 0L;
                    int  expo       = -(endPos - (decimalPointPos + 1));
                    int  vi         = numOffset;
                    var  digitCount = 0;
                    for (; vi < decimalPointPos; ++vi)
                    {
                        if (digitCount < 0 || digitCount >= 18)
                        {
                            digitCount = -1;
                            break;
                        }
                        else if (digitCount > 0 || chars[vi] != '0')
                        {
                            ++digitCount;
                        }
                        lv = checked ((lv * 10) + (int)(chars[vi] - '0'));
                    }
                    for (vi = decimalPointPos + 1; vi < endPos; ++vi)
                    {
                        if (digitCount < 0 || digitCount >= 18)
                        {
                            digitCount = -1;
                            break;
                        }
                        else if (digitCount > 0 || chars[vi] != '0')
                        {
                            ++digitCount;
                        }
                        lv = checked ((lv * 10) + (int)(chars[vi] - '0'));
                    }
                    if (negative)
                    {
                        lv = -lv;
                    }
                    if (digitCount >= 0 && (!negative || lv != 0))
                    {
                        if (expo == 0)
                        {
                            return(CBORObject.FromObject(lv));
                        }
                        else
                        {
                            CBORObject cbor = CBORObject.FromArrayBackedObject(
                                new CBORObject[] {
                                CBORObject.FromObject(expo),
                                CBORObject.FromObject(lv),
                            });
                            return(cbor.WithTag(4));
                        }
                    }
                }
                // DebugUtility.Log("convfull " + chars.Substring(initialOffset, endPos -
                // initialOffset));
                EDecimal ed = EDecimal.FromString(
                    chars,
                    initialOffset,
                    endPos - initialOffset);
                if (ed.IsZero && negative)
                {
                    if (ed.Exponent.IsZero)
                    {
                        // TODO: In next major version, use EDecimal
                        // for preserveNegativeZero
                        return(preserveNegativeZero ?
                               CBORObject.FromFloatingPointBits(0x8000, 2) :
                               CBORObject.FromObject(0));
                    }
                    else if (!preserveNegativeZero)
                    {
                        return(CBORObject.FromObject(ed.Negate()));
                    }
                    else
                    {
                        return(CBORObject.FromObject(ed));
                    }
                }
                else
                {
                    return(ed.Exponent.IsZero ? CBORObject.FromObject(ed.Mantissa) :
                           CBORObject.FromObject(ed));
                }
            }
            else if (kind == JSONOptions.ConversionMode.Double)
            {
                EFloat ef = EFloat.FromString(
                    chars,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Binary64);
                long lb = ef.ToDoubleBits();
                if (!preserveNegativeZero && (lb == 1L << 63 || lb == 0L))
                {
                    lb = 0L;
                }
                return(CBORObject.FromFloatingPointBits(lb, 8));
            }
            else if (kind == JSONOptions.ConversionMode.Decimal128)
            {
                EDecimal ed = EDecimal.FromString(
                    chars,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Decimal128);
                if (!preserveNegativeZero && ed.IsNegative && ed.IsZero)
                {
                    ed = ed.Negate();
                }
                return(CBORObject.FromObject(ed));
            }
            else if (kind == JSONOptions.ConversionMode.IntOrFloatFromDouble)
            {
                EFloat ef = EFloat.FromString(
                    chars,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Binary64);
                long lb = ef.ToDoubleBits();
                return((!CBORUtilities.IsBeyondSafeRange(lb) &&
                        CBORUtilities.IsIntegerValue(lb)) ?
                       CBORObject.FromObject(CBORUtilities.GetIntegerValue(lb)) :
                       CBORObject.FromFloatingPointBits(lb, 8));
            }
            else if (kind == JSONOptions.ConversionMode.IntOrFloat)
            {
                EContext ctx = EContext.Binary64.WithBlankFlags();
                EFloat   ef  = EFloat.FromString(
                    chars,
                    initialOffset,
                    endPos - initialOffset,
                    ctx);
                long lb = ef.ToDoubleBits();
                if ((ctx.Flags & EContext.FlagInexact) != 0)
                {
                    // Inexact conversion to double, meaning that the string doesn't
                    // represent an integer in [-(2^53)+1, 2^53), which is representable
                    // exactly as double, so treat as ConversionMode.Double
                    if (!preserveNegativeZero && (lb == 1L << 63 || lb == 0L))
                    {
                        lb = 0L;
                    }
                    return(CBORObject.FromFloatingPointBits(lb, 8));
                }
                else
                {
                    // Exact conversion; treat as ConversionMode.IntToFloatFromDouble
                    return((!CBORUtilities.IsBeyondSafeRange(lb) &&
                            CBORUtilities.IsIntegerValue(lb)) ?
                           CBORObject.FromObject(CBORUtilities.GetIntegerValue(lb)) :
                           CBORObject.FromFloatingPointBits(lb, 8));
                }
            }
            else
            {
                throw new ArgumentException("Unsupported conversion kind.");
            }
        }
Пример #29
0
        /// <summary>
        ///
        /// Term syntax:
        ///   Term -> Identifier
        ///         | FloatNumber
        ///         | DecimalNumber
        ///         | String
        ///         | "(" Expression ")"
        ///         | Lambda
        //          | CompilerIdentifier "(" ( Expression ( "," Expression )* )? ")"
        ///
        ///   Lambda -> KeywordProc "(" (Argument ( "," Argument )* )? ")" ( -> TypeInfo )?
        ///   Argument -> Identifier ":" TypeInfo ( "=" Expression )?
        ///
        /// </summary>
        /// <returns></returns>
        private ASTNode ParseTerm()
        {
            // Identifier
            if (EatToken(TokenKind.Identifier))
            {
                return(new ASTSymbol(EatenToken.Position, EatenToken.Value));
            }

            // FloatNumber
            if (EatToken(TokenKind.FloatNumber))
            {
                return(new ASTFloatLiteral(EatenToken.Position, EDecimal.FromString(EatenToken.Value)));
            }

            // DecimalNumber
            if (EatToken(TokenKind.DecimalNumber))
            {
                return(new ASTIntegerLiteral(EatenToken.Position, EInteger.FromString(EatenToken.Value)));
            }

            // String
            if (EatToken(TokenKind.String))
            {
                return(new ASTStringLiteral(EatenToken.Position, EatenToken.Value));
            }

            // "(" Expression ")"
            if (EatToken(TokenKind.ParenthesesLeft))
            {
                var start      = EatenToken;
                var expression = ParseExpression();
                if (expression == null)
                {
                    return(null);
                }

                return(Expect(TokenKind.ParenthesesRight) ? new ASTParentheses(start.Position)
                {
                    Child = expression
                } : null);
            }

            //   Lambda -> KeywordProc "(" (Argument ( "," Argument )* )? ")" ( -> TypeInfo )?
            if (EatToken(t => t == TokenKind.KeywordFunction || t == TokenKind.KeywordProcedure))
            {
                var start = EatenToken;
                if (!Expect(TokenKind.ParenthesesLeft))
                {
                    return(null);
                }

                var arguments = ParseMany(TokenKind.ParenthesesRight, TokenKind.Comma, () =>
                {
                    var ident = PeekToken();
                    if (!Expect(TokenKind.Identifier))
                    {
                        return(null);
                    }
                    if (!Expect(TokenKind.Colon))
                    {
                        return(null);
                    }

                    var type = ParseType();
                    if (type == null)
                    {
                        return(null);
                    }

                    ASTNode defaultValue = null;
                    if (EatToken(TokenKind.Equal))
                    {
                        defaultValue = ParseExpression();
                        if (defaultValue == null)
                        {
                            return(null);
                        }
                    }

                    return(new ASTLambda.Argument(ident.Position)
                    {
                        Name = ident.Value,
                        Type = type,
                        DefaultValue = defaultValue
                    });
                });

                if (arguments == null)
                {
                    return(null);
                }

                ASTNode returnType = null;
                if (EatToken(TokenKind.Arrow))
                {
                    returnType = ParseType();
                    if (returnType == null)
                    {
                        return(null);
                    }
                }

                var block = ParseCodeBlock();
                if (block == null)
                {
                    return(null);
                }

                return(new ASTLambda(start.Position)
                {
                    Block = block,
                    Return = returnType,
                    Arguments = arguments
                });
            }

            if (PeekTokenIs(TokenKind.CompilerIdentifier))
            {
                return(ParseCompilerCall());
            }

            Error(peek => $"While parsing a term, the parser found an unexpected token: {peek.Kind}");
            return(null);
        }
Пример #30
0
        public void TestAsEInteger()
        {
            try {
                ToObjectTest.TestToFromObjectRoundTrip(
                    (object)null).AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (InvalidOperationException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            try {
                CBORObject.Null.AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (InvalidOperationException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            try {
                CBORObject.True.AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (InvalidOperationException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            try {
                CBORObject.False.AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (InvalidOperationException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            try {
                CBORObject.Undefined.AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (InvalidOperationException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            try {
                CBORObject.NewArray().AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (InvalidOperationException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            try {
                CBORObject.NewMap().AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (InvalidOperationException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            CBORObject numbers = CBORObjectTest.GetNumberData();

            for (int i = 0; i < numbers.Count; ++i)
            {
                CBORObject numberinfo   = numbers[i];
                string     numberString = numberinfo["number"].AsString();
                CBORObject cbornumber   =
                    ToObjectTest.TestToFromObjectRoundTrip(EDecimal.FromString(
                                                               numberString));
                if (!numberinfo["integer"].Equals(CBORObject.Null))
                {
                    Assert.AreEqual(
                        numberinfo["integer"].AsString(),
                        cbornumber.AsNumber().ToEInteger().ToString());
                }
                else
                {
                    try {
                        cbornumber.AsNumber().ToEInteger();
                        Assert.Fail("Should have failed");
                    } catch (OverflowException) {
                        // NOTE: Intentionally empty
                    } catch (Exception ex) {
                        Assert.Fail(ex.ToString());
                        throw new InvalidOperationException(String.Empty, ex);
                    }
                }
            }

            {
                string stringTemp =
                    ToObjectTest.TestToFromObjectRoundTrip(0.75f).AsNumber().ToEInteger()
                    .ToString();
                Assert.AreEqual(
                    "0",
                    stringTemp);
            }
            {
                string stringTemp =
                    ToObjectTest.TestToFromObjectRoundTrip(0.99f).AsNumber().ToEInteger()
                    .ToString();
                Assert.AreEqual(
                    "0",
                    stringTemp);
            }
            {
                string stringTemp =
                    ToObjectTest.TestToFromObjectRoundTrip(0.0000000000000001f)
                    .AsNumber().ToEInteger().ToString();
                Assert.AreEqual(
                    "0",
                    stringTemp);
            }
            {
                string stringTemp =
                    ToObjectTest.TestToFromObjectRoundTrip(0.5f).AsNumber().ToEInteger()
                    .ToString();
                Assert.AreEqual(
                    "0",
                    stringTemp);
            }
            {
                string stringTemp =
                    ToObjectTest.TestToFromObjectRoundTrip(1.5f).AsNumber().ToEInteger()
                    .ToString();
                Assert.AreEqual(
                    "1",
                    stringTemp);
            }
            {
                string stringTemp =
                    ToObjectTest.TestToFromObjectRoundTrip(2.5f).AsNumber().ToEInteger()
                    .ToString();
                Assert.AreEqual(
                    "2",
                    stringTemp);
            }
            {
                string stringTemp =

                    ToObjectTest.TestToFromObjectRoundTrip(
                        (float)328323f).AsNumber().ToEInteger().ToString();
                Assert.AreEqual(
                    "328323",
                    stringTemp);
            }
            {
                string stringTemp =
                    ToObjectTest.TestToFromObjectRoundTrip(
                        (double)0.75).AsNumber().ToEInteger()
                    .ToString();
                Assert.AreEqual(
                    "0",
                    stringTemp);
            }
            {
                string stringTemp = ToObjectTest.TestToFromObjectRoundTrip(
                    (double)0.99).AsNumber().ToEInteger().ToString();
                Assert.AreEqual(
                    "0",
                    stringTemp);
            }
            {
                string stringTemp =
                    ToObjectTest.TestToFromObjectRoundTrip((double)0.0000000000000001)
                    .AsNumber().ToEInteger().ToString();
                Assert.AreEqual(
                    "0",
                    stringTemp);
            }
            {
                string stringTemp = ToObjectTest.TestToFromObjectRoundTrip(
                    (double)0.5).AsNumber().ToEInteger().ToString();
                Assert.AreEqual(
                    "0",
                    stringTemp);
            }
            {
                string stringTemp =
                    ToObjectTest.TestToFromObjectRoundTrip(
                        (double)1.5).AsNumber().ToEInteger()
                    .ToString();
                Assert.AreEqual(
                    "1",
                    stringTemp);
            }
            {
                string stringTemp = ToObjectTest.TestToFromObjectRoundTrip(
                    (double)2.5).AsNumber().ToEInteger().ToString();
                Assert.AreEqual(
                    "2",
                    stringTemp);
            }
            {
                double dbl        = 328323;
                string stringTemp = ToObjectTest.TestToFromObjectRoundTrip(dbl)
                                    .AsNumber().ToEInteger().ToString();
                Assert.AreEqual(
                    "328323",
                    stringTemp);
            }
            try {
                ToObjectTest.TestToFromObjectRoundTrip(Single.PositiveInfinity)
                .AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (OverflowException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            try {
                ToObjectTest.TestToFromObjectRoundTrip(Single.NegativeInfinity)
                .AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (OverflowException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            try {
                ToObjectTest.TestToFromObjectRoundTrip(
                    Single.NaN).AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (OverflowException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            try {
                ToObjectTest.TestToFromObjectRoundTrip(Double.PositiveInfinity)
                .AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (OverflowException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            try {
                ToObjectTest.TestToFromObjectRoundTrip(Double.NegativeInfinity)
                .AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (OverflowException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
            try {
                ToObjectTest.TestToFromObjectRoundTrip(
                    Double.NaN).AsNumber().ToEInteger();
                Assert.Fail("Should have failed");
            } catch (OverflowException) {
                // NOTE: Intentionally empty
            } catch (Exception ex) {
                Assert.Fail(ex.ToString());
                throw new InvalidOperationException(String.Empty, ex);
            }
        }