Beispiel #1
0
        public bool Equals(SqlNumber other)
        {
            if (State == NumericState.NegativeInfinity &&
                other.State == NumericState.NegativeInfinity)
            {
                return(true);
            }
            if (State == NumericState.PositiveInfinity &&
                other.State == NumericState.PositiveInfinity)
            {
                return(true);
            }
            if (State == NumericState.NotANumber &&
                other.State == NumericState.NotANumber)
            {
                return(true);
            }

            if (IsNull && other.IsNull)
            {
                return(true);
            }
            if (IsNull && !other.IsNull)
            {
                return(false);
            }
            if (!IsNull && other.IsNull)
            {
                return(false);
            }

            return(innerValue.CompareTo(other.innerValue) == 0);
        }
Beispiel #2
0
        public bool Equals(SqlNumber other)
        {
            if (state != other.state)
            {
                return(false);
            }

            if (state != NumericState.None)
            {
                return(true);
            }

            return(innerValue.CompareTo(other.innerValue) == 0);
        }
Beispiel #3
0
        public BigDecimal Get(BigDecimal n)
        {
            if (n.CompareTo(ZERO) <= 0)
            {
                throw new System.ArgumentException();
            }

            BigDecimal initialGuess = GetInitialApproximation(n);
            BigDecimal lastGuess    = ZERO;
            BigDecimal guess        = new BigDecimal(initialGuess.ToString());

            int  iterations = 0;
            bool more       = true;

            while (more)
            {
                lastGuess = guess;
                guess     = n.divide(guess, scale, BigDecimal.ROUND_HALF_UP);
                guess     = guess.add(lastGuess);
                guess     = guess.divide(TWO, scale, BigDecimal.ROUND_HALF_UP);
                error     = n.subtract(guess.multiply(guess));
                if (++iterations >= maxIterations)
                {
                    more = false;
                }
                else if (lastGuess.Equals(guess))
                {
                    more = error.abs().CompareTo(ONE) >= 0;
                }
            }
            return(guess);
        }
Beispiel #4
0
 public static void CheckUpperBound(BigDecimal val)
 {
     if (val.CompareTo(MaxNativeValue) == 1)
     {
         throw GetOutOfBoundsException(val, "bigger", MaxNativeValue);
     }
 }
Beispiel #5
0
        /// <summary>Returns a list of BigDecimals one element longer than the list of input splits.
        ///     </summary>
        /// <remarks>
        /// Returns a list of BigDecimals one element longer than the list of input splits.
        /// This represents the boundaries between input splits.
        /// All splits are open on the top end, except the last one.
        /// So the list [0, 5, 8, 12, 18] would represent splits capturing the intervals:
        /// [0, 5)
        /// [5, 8)
        /// [8, 12)
        /// [12, 18] note the closed interval for the last split.
        /// </remarks>
        /// <exception cref="Java.Sql.SQLException"/>
        internal virtual IList <BigDecimal> Split(BigDecimal numSplits, BigDecimal minVal,
                                                  BigDecimal maxVal)
        {
            IList <BigDecimal> splits = new AList <BigDecimal>();
            // Use numSplits as a hint. May need an extra task if the size doesn't
            // divide cleanly.
            BigDecimal splitSize = TryDivide(maxVal.Subtract(minVal), (numSplits));

            if (splitSize.CompareTo(MinIncrement) < 0)
            {
                splitSize = MinIncrement;
                Log.Warn("Set BigDecimal splitSize to MIN_INCREMENT");
            }
            BigDecimal curVal = minVal;

            while (curVal.CompareTo(maxVal) <= 0)
            {
                splits.AddItem(curVal);
                curVal = curVal.Add(splitSize);
            }
            if (splits[splits.Count - 1].CompareTo(maxVal) != 0 || splits.Count == 1)
            {
                // We didn't end on the maxVal. Add that to the end of the list.
                splits.AddItem(maxVal);
            }
            return(splits);
        }
Beispiel #6
0
        public void CompareToTest()
        {
            var v1 = new BigDecimal(100.001m);
            var v2 = new BigDecimal(100.001m);

            Assert.IsTrue(v1.CompareTo(v2) == 0);
        }
Beispiel #7
0
        public void Compare_MultipleValues_Pass()
        {
            var num1     = new BigDecimal(20);
            var num2     = new BigDecimal(30);
            var actual   = num1.CompareTo(num2);
            var expected = -1;

            Assert.AreEqual(expected, actual);

            actual   = num1.CompareTo(num1);
            expected = 0;
            Assert.AreEqual(expected, actual);

            actual   = num2.CompareTo(num1);
            expected = 1;
            Assert.AreEqual(expected, actual);
        }
Beispiel #8
0
 public void CompareToBigDecimal()
 {
     BigDecimal comp1 = BigDecimal.Parse("1.00");
     BigDecimal comp2 = new BigDecimal(1.000000D);
     Assert.IsTrue(comp1.CompareTo(comp2) == 0, "1.00 and 1.000000 should be equal");
     BigDecimal comp3 = BigDecimal.Parse("1.02");
     Assert.IsTrue(comp3.CompareTo(comp1) == 1, "1.02 should be bigger than 1.00");
     BigDecimal comp4 = new BigDecimal(0.98D);
     Assert.IsTrue(comp4.CompareTo(comp1) == -1, "0.98 should be less than 1.00");
 }
Beispiel #9
0
        public String Format(BigDecimal b, int maxLength, int maxNumberOfIntegers, int maxNumberOfDecimals, bool padFractions)
        {
            String basePattern = "0." + StringUtils.Repeat(padFractions ? "0" : "#", maxNumberOfDecimals);
            String text        = String.Format("{0:" + basePattern + "}", (decimal)b);

            // the above takes care of the decimals having too many digits; now to handle digits to left of decimal.
            // this code preserves a negative sign to match what the java code does (this is possibly not ideal)
            int decimalLocation = text.IndexOf(".");

            if (decimalLocation > maxNumberOfIntegers)
            {
                return((b.CompareTo(BigDecimal.ZERO) < 0 ? "-" : "") + text.Substring(decimalLocation - maxNumberOfIntegers));
            }
            else if (decimalLocation == -1 && text.Length > maxNumberOfIntegers)
            {
                return((b.CompareTo(BigDecimal.ZERO) < 0 ? "-" : "") + text.Substring(text.Length - maxNumberOfIntegers));
            }
            else
            {
                return(text);
            }
        }
Beispiel #10
0
        public BigDecimal calDens(BigDecimal radius)
        {
            BigDecimal vol  = BigDecimal.Parse("0.0");
            BigDecimal num  = BigDecimal.Parse("1.33333333333");
            BigDecimal pi   = BigDecimal.Parse(Math.PI.ToString());
            BigDecimal mass = BigInteger.Parse("1990000000000000000000000000000");
            BigDecimal dens = BigDecimal.Parse("0.0");

            num  = num.Multiply(pi);
            vol  = radius.Pow(3);
            vol  = num.Multiply(vol);
            dens = mass / (vol);

            //while (mass.compareTo(vol.toBigInteger()) < 0)
            while (mass.CompareTo(((BigInteger)vol)) < 0)
            {
                if (type == ("Average_Star"))
                {
                    mass = range(Average_Starmax, Average_Starmin);
                }
                if (type == ("Massive_Star"))
                {
                    mass = range(Massive_Starmax, Massive_Starmin);
                }
                if (type == ("White_Dwarf"))
                {
                    mass = range(White_Dwarfmax, White_Dwarfmin);
                }
                if (type == ("Neutron_Star"))
                {
                    mass = range(Neutron_Starmax, Neutron_Starmin);
                }
                if (type == ("Black_hole"))
                {
                    mass = range(Black_holemax, Black_holemin);
                }
                else
                {
                    break;
                }
            }


            dens    = mass / (vol);
            density = dens;
            //if(density.compareTo(BigDecimal.Parse("1")) < 0 ){
            //   Console.WriteLine("its 0");
            //    System.exit(0);
            //}
            return(dens);
        }
Beispiel #11
0
 public Number Divide(Number number)
 {
     if (numberState == 0)
     {
         if (number.numberState == 0)
         {
             BigDecimal divBy = number.bigDecimal;
             if (divBy.CompareTo(BdZero) != 0)
             {
                 return(new Number(NumberState.None, bigDecimal.Divide(divBy, 10, RoundingMode.HalfUp)));
             }
         }
     }
     // Return NaN if we can't divide
     return(new Number(NumberState.NotANumber, null));
 }
Beispiel #12
0
        public static SqlNumber Remainder(SqlNumber a, SqlNumber b)
        {
            if (SqlNumber.IsNumber(a))
            {
                if (SqlNumber.IsNumber(b))
                {
                    BigDecimal divBy = b.innerValue;
                    if (divBy.CompareTo(BigDecimal.Zero) != 0)
                    {
                        var remainder = BigMath.Remainder(a.innerValue, divBy);
                        return(new SqlNumber(SqlNumber.NumericState.None, remainder));
                    }
                }
            }

            return(SqlNumber.NaN);
        }
Beispiel #13
0
        public Number Modulus(Number number)
        {
            if (numberState == 0)
            {
                if (number.numberState == 0)
                {
                    BigDecimal divBy = number.bigDecimal;
                    if (divBy.CompareTo(BdZero) != 0)
                    {
                        BigDecimal remainder = bigDecimal.Remainder(divBy);
                        return(new Number(NumberState.None, remainder));
                    }
                }
            }

            return(new Number(NumberState.NotANumber, null));
        }
Beispiel #14
0
        private static BigDecimal SqrtNewtonRaphson(BigDecimal c, BigDecimal xn, BigDecimal precision)
        {
            BigDecimal fx  = xn.Pow(2).Add(c.Negate());
            BigDecimal fpx = xn.Multiply(new BigDecimal(2));
            BigDecimal xn1 = fx.Divide(fpx, 2 * SqrtDig.ToInt32(), RoundingMode.HalfDown);

            xn1 = xn.Add(xn1.Negate());
            //----
            BigDecimal currentSquare    = xn1.Pow(2);
            BigDecimal currentPrecision = currentSquare.Subtract(c);

            currentPrecision = currentPrecision.Abs();
            if (currentPrecision.CompareTo(precision) <= -1)
            {
                return(xn1);
            }

            return(SqrtNewtonRaphson(c, xn1, precision));
        }
Beispiel #15
0
        public static SqlNumber Divide(SqlNumber a, SqlNumber b, int precision)
        {
            if (SqlNumber.IsNumber(a))
            {
                if (SqlNumber.IsNumber(b))
                {
                    BigDecimal divBy = b.innerValue;
                    if (divBy.CompareTo(BigDecimal.Zero) != 0)
                    {
                        var context = new MathContext(precision);
                        var result  = BigMath.Divide(a.innerValue, divBy, context);
                        return(new SqlNumber(SqlNumber.NumericState.None, result));
                    }
                    throw new DivideByZeroException();
                }
            }

            // Return NaN if we can't divide
            return(SqlNumber.NaN);
        }
Beispiel #16
0
        public SqlNumber Modulo(SqlNumber value)
        {
            if (State == NumericState.None)
            {
                if (value.State == NumericState.None)
                {
                    if (IsNull || value.IsNull)
                    {
                        return(Null);
                    }

                    BigDecimal divBy = value.innerValue;
                    if (divBy.CompareTo(BigDecimal.Zero) != 0)
                    {
                        BigDecimal remainder = innerValue.Remainder(divBy);
                        return(new SqlNumber(NumericState.None, remainder));
                    }
                }
            }

            return(new SqlNumber(NumericState.NotANumber, null));
        }
Beispiel #17
0
        public SqlNumber Divide(SqlNumber value)
        {
            if (State == NumericState.None)
            {
                if (value.State == NumericState.None)
                {
                    if (IsNull || value.IsNull)
                    {
                        return(Null);
                    }

                    BigDecimal divBy = value.innerValue;
                    if (divBy.CompareTo(BigDecimal.Zero) != 0)
                    {
                        return(new SqlNumber(NumericState.None, innerValue.Divide(divBy, 10, RoundingMode.HalfUp)));
                    }
                }
            }

            // Return NaN if we can't divide
            return(new SqlNumber(NumericState.NotANumber, null));
        }
Beispiel #18
0
        public static BigDecimal Exp(BigDecimal x)
        {
            /* To calculate the value if x is negative, use exp(-x) = 1/exp(x)
                */
            if (x.CompareTo(BigDecimal.Zero) < 0) {
                BigDecimal invx = Exp(x.Negate());
                /* Relative error in inverse of invx is the same as the relative errror in invx.
                        * This is used to define the precision of the result.
                        */
                var mc = new MathContext(invx.Precision);
                return BigDecimal.One.Divide(invx, mc);
            }
            if (x.CompareTo(BigDecimal.Zero) == 0) {
                /* recover the valid number of digits from x.ulp(), if x hits the
                        * zero. The x.precision() is 1 then, and does not provide this information.
                        */
                return ScalePrecision(BigDecimal.One, -(int) (System.Math.Log10(x.Ulp().ToDouble())));
            }
            /* Push the number in the Taylor expansion down to a small
                        * value where TAYLOR_NTERM terms will do. If x<1, the n-th term is of the order
                        * x^n/n!, and equal to both the absolute and relative error of the result
                        * since the result is close to 1. The x.ulp() sets the relative and absolute error
                        * of the result, as estimated from the first Taylor term.
                        * We want x^TAYLOR_NTERM/TAYLOR_NTERM! < x.ulp, which is guaranteed if
                        * x^TAYLOR_NTERM < TAYLOR_NTERM*(TAYLOR_NTERM-1)*...*x.ulp.
                        */
            double xDbl = x.ToDouble();
            double xUlpDbl = x.Ulp().ToDouble();
            if (System.Math.Pow(xDbl, TaylorNterm) < TaylorNterm*(TaylorNterm - 1.0)*(TaylorNterm - 2.0)*xUlpDbl) {
                /* Add TAYLOR_NTERM terms of the Taylor expansion (Euler's sum formula)
                                */
                BigDecimal resul = BigDecimal.One;

                /* x^i */
                BigDecimal xpowi = BigDecimal.One;

                /* i factorial */
                BigInteger ifac = BigInteger.One;

                /* TAYLOR_NTERM terms to be added means we move x.ulp() to the right
                                * for each power of 10 in TAYLOR_NTERM, so the addition won't add noise beyond
                                * what's already in x.
                                */
                var mcTay = new MathContext(ErrorToPrecision(1d, xUlpDbl/TaylorNterm));
                for (int i = 1; i <= TaylorNterm; i++) {
                    ifac = ifac.Multiply(BigInteger.ValueOf(i));
                    xpowi = xpowi.Multiply(x);
                    BigDecimal c = xpowi.Divide(new BigDecimal(ifac), mcTay);
                    resul = resul.Add(c);
                    if (System.Math.Abs(xpowi.ToDouble()) < i &&
                        System.Math.Abs(c.ToDouble()) < 0.5*xUlpDbl)
                        break;
                }
                /* exp(x+deltax) = exp(x)(1+deltax) if deltax is <<1. So the relative error
                                * in the result equals the absolute error in the argument.
                                */
                var mc = new MathContext(ErrorToPrecision(xUlpDbl/2d));
                return resul.Round(mc);
            } else {
                /* Compute exp(x) = (exp(0.1*x))^10. Division by 10 does not lead
                                * to loss of accuracy.
                                */
                var exSc = (int) (1.0 - System.Math.Log10(TaylorNterm*(TaylorNterm - 1.0)*(TaylorNterm - 2.0)*xUlpDbl
                                                          /System.Math.Pow(xDbl, TaylorNterm))/(TaylorNterm - 1.0));
                BigDecimal xby10 = x.ScaleByPowerOfTen(-exSc);
                BigDecimal expxby10 = Exp(xby10);

                /* Final powering by 10 means that the relative error of the result
                                * is 10 times the relative error of the base (First order binomial expansion).
                                * This looses one digit.
                                */
                var mc = new MathContext(expxby10.Precision - exSc);
                /* Rescaling the powers of 10 is done in chunks of a maximum of 8 to avoid an invalid operation
                                * response by the BigDecimal.pow library or integer overflow.
                                */
                while (exSc > 0) {
                    int exsub = System.Math.Min(8, exSc);
                    exSc -= exsub;
                    var mctmp = new MathContext(expxby10.Precision - exsub + 2);
                    int pex = 1;
                    while (exsub-- > 0)
                        pex *= 10;
                    expxby10 = expxby10.Pow(pex, mctmp);
                }
                return expxby10.Round(mc);
            }
        }
Beispiel #19
0
        public static BigDecimal Cot(BigDecimal x)
        {
            if (x.CompareTo(BigDecimal.Zero) == 0) {
                throw new ArithmeticException("Cannot take cot of zero " + x);
            }
            if (x.CompareTo(BigDecimal.Zero) < 0) {
                return Cot(x.Negate()).Negate();
            }
            /* reduce modulo pi
                        */
            BigDecimal res = ModPi(x);

            /* absolute error in the result is err(x)/sin^2(x) to lowest order
                        */
            double xDbl = res.ToDouble();
            double xUlpDbl = x.Ulp().ToDouble()/2d;
            double eps = xUlpDbl/2d/System.Math.Pow(System.Math.Sin(xDbl), 2d);

            BigDecimal xhighpr = ScalePrecision(res, 2);
            BigDecimal xhighprSq = MultiplyRound(xhighpr, xhighpr);

            var mc = new MathContext(ErrorToPrecision(xhighpr.ToDouble(), eps));
            BigDecimal resul = BigDecimal.One.Divide(xhighpr, mc);

            /* x^(2i-1) */
            BigDecimal xpowi = xhighpr;

            var b = new Bernoulli();

            /* 2^(2i) */
            var fourn = BigInteger.Parse("4");
            /* (2i)! */
            BigInteger fac = BigInteger.One;

            for (int i = 1;; i++) {
                Rational f = b[2*i];
                fac = fac.Multiply(BigInteger.ValueOf((2*i))).Multiply(BigInteger.ValueOf((2*i - 1)));
                f = f.Multiply(fourn).Divide(fac);
                BigDecimal c = MultiplyRound(xpowi, f);
                if (i%2 == 0)
                    resul = resul.Add(c);
                else
                    resul = resul.Subtract(c);
                if (System.Math.Abs(c.ToDouble()) < 0.1*eps)
                    break;

                fourn = fourn.ShiftLeft(2);
                xpowi = MultiplyRound(xpowi, xhighprSq);
            }
            mc = new MathContext(ErrorToPrecision(resul.ToDouble(), eps));
            return resul.Round(mc);
        }
Beispiel #20
0
        public static BigDecimal Cos(BigDecimal x)
        {
            if (x.CompareTo(BigDecimal.Zero) < 0)
                return Cos(x.Negate());
            if (x.CompareTo(BigDecimal.Zero) == 0)
                return BigDecimal.One;
            /* reduce modulo 2pi
                        */
            BigDecimal res = Mod2Pi(x);
            double errpi = 0.5*System.Math.Abs(x.Ulp().ToDouble());
            var mc = new MathContext(2 + ErrorToPrecision(3.14159, errpi));
            BigDecimal p = PiRound(mc);
            mc = new MathContext(x.Precision);
            if (res.CompareTo(p) > 0) {
                /* pi<x<=2pi: cos(x)= - cos(x-pi)
                                */
                return Cos(SubtractRound(res, p)).Negate();
            }
            if (res.Multiply(BigDecimal.ValueOf(2)).CompareTo(p) > 0) {
                /* pi/2<x<=pi: cos(x)= -cos(pi-x)
                                */
                return Cos(SubtractRound(p, res)).Negate();
            }
            /* for the range 0<=x<Pi/2 one could use cos(2x)= 1-2*sin^2(x)
                                * to split this further, or use the cos up to pi/4 and the sine higher up.
                                        throw new ProviderException("Not implemented: cosine ") ;
                                */
            if (res.Multiply(BigDecimal.ValueOf(4)).CompareTo(p) > 0) {
                /* x>pi/4: cos(x) = sin(pi/2-x)
                                        */
                return Sin(SubtractRound(p.Divide(BigDecimal.ValueOf(2)), res));
            }
            /* Simple Taylor expansion, sum_{i=0..infinity} (-1)^(..)res^(2i)/(2i)! */
            BigDecimal resul = BigDecimal.One;

            /* x^i */
            BigDecimal xpowi = BigDecimal.One;

            /* 2i factorial */
            BigInteger ifac = BigInteger.One;

            /* The absolute error in the result is the error in x^2/2 which is x times the error in x.
                                        */
            double xUlpDbl = 0.5*res.Ulp().ToDouble()*res.ToDouble();

            /* The error in the result is set by the error in x^2/2 itself, xUlpDbl.
                                        * We need at most k terms to push x^(2k+1)/(2k+1)! below this value.
                                        * x^(2k) < xUlpDbl; (2k)*log(x) < log(xUlpDbl);
                                        */
            int k = (int) (System.Math.Log(xUlpDbl)/System.Math.Log(res.ToDouble()))/2;
            var mcTay = new MathContext(ErrorToPrecision(1d, xUlpDbl/k));
            for (int i = 1;; i++) {
                /* TBD: at which precision will 2*i-1 or 2*i overflow?
                                                */
                ifac = ifac.Multiply(BigInteger.ValueOf((2*i - 1)));
                ifac = ifac.Multiply(BigInteger.ValueOf((2*i)));
                xpowi = xpowi.Multiply(res).Multiply(res).Negate();
                BigDecimal corr = xpowi.Divide(new BigDecimal(ifac), mcTay);
                resul = resul.Add(corr);
                if (corr.Abs().ToDouble() < 0.5*xUlpDbl)
                    break;
            }
            /* The error in the result is governed by the error in x itself.
                                        */
            mc = new MathContext(ErrorToPrecision(resul.ToDouble(), xUlpDbl));
            return resul.Round(mc);
        }
Beispiel #21
0
 public static BigDecimal Cbrt(BigDecimal x)
 {
     if (x.CompareTo(BigDecimal.Zero) < 0)
         return Root(3, x.Negate()).Negate();
     return Root(3, x);
 }
Beispiel #22
0
        public static BigDecimal Asin(BigDecimal x)
        {
            if (x.CompareTo(BigDecimal.One) > 0 ||
                x.CompareTo(BigDecimal.One.Negate()) < 0) {
                throw new ArithmeticException("Out of range argument " + x + " of asin");
            }
            if (x.CompareTo(BigDecimal.Zero) == 0)
                return BigDecimal.Zero;
            if (x.CompareTo(BigDecimal.One) == 0) {
                /* arcsin(1) = pi/2
                        */
                double errpi = System.Math.Sqrt(x.Ulp().ToDouble());
                var mc = new MathContext(ErrorToPrecision(3.14159, errpi));
                return PiRound(mc).Divide(new BigDecimal(2));
            }
            if (x.CompareTo(BigDecimal.Zero) < 0) {
                return Asin(x.Negate()).Negate();
            }
            if (x.ToDouble() > 0.7) {
                BigDecimal xCompl = BigDecimal.One.Subtract(x);
                double xDbl = x.ToDouble();
                double xUlpDbl = x.Ulp().ToDouble()/2d;
                double eps = xUlpDbl/2d/System.Math.Sqrt(1d - System.Math.Pow(xDbl, 2d));

                BigDecimal xhighpr = ScalePrecision(xCompl, 3);
                BigDecimal xhighprV = DivideRound(xhighpr, 4);

                BigDecimal resul = BigDecimal.One;

                /* x^(2i+1) */
                BigDecimal xpowi = BigDecimal.One;

                /* i factorial */
                BigInteger ifacN = BigInteger.One;
                BigInteger ifacD = BigInteger.One;

                for (int i = 1;; i++) {
                    ifacN = ifacN.Multiply(BigInteger.ValueOf((2*i - 1)));
                    ifacD = ifacD.Multiply(BigInteger.ValueOf(i));
                    if (i == 1)
                        xpowi = xhighprV;
                    else
                        xpowi = MultiplyRound(xpowi, xhighprV);
                    BigDecimal c = DivideRound(MultiplyRound(xpowi, ifacN),
                        ifacD.Multiply(BigInteger.ValueOf((2*i + 1))));
                    resul = resul.Add(c);
                    /* series started 1+x/12+... which yields an estimate of the sum's error
                                */
                    if (System.Math.Abs(c.ToDouble()) < xUlpDbl/120d)
                        break;
                }
                /* sqrt(2*z)*(1+...)
                        */
                xpowi = Sqrt(xhighpr.Multiply(new BigDecimal(2)));
                resul = MultiplyRound(xpowi, resul);

                var mc = new MathContext(resul.Precision);
                BigDecimal pihalf = PiRound(mc).Divide(new BigDecimal(2));

                mc = new MathContext(ErrorToPrecision(resul.ToDouble(), eps));
                return pihalf.Subtract(resul, mc);
            } else {
                /* absolute error in the result is err(x)/sqrt(1-x^2) to lowest order
                        */
                double xDbl = x.ToDouble();
                double xUlpDbl = x.Ulp().ToDouble()/2d;
                double eps = xUlpDbl/2d/System.Math.Sqrt(1d - System.Math.Pow(xDbl, 2d));

                BigDecimal xhighpr = ScalePrecision(x, 2);
                BigDecimal xhighprSq = MultiplyRound(xhighpr, xhighpr);

                BigDecimal resul = xhighpr.Plus();

                /* x^(2i+1) */
                BigDecimal xpowi = xhighpr;

                /* i factorial */
                BigInteger ifacN = BigInteger.One;
                BigInteger ifacD = BigInteger.One;

                for (int i = 1;; i++) {
                    ifacN = ifacN.Multiply(BigInteger.ValueOf((2*i - 1)));
                    ifacD = ifacD.Multiply(BigInteger.ValueOf((2*i)));
                    xpowi = MultiplyRound(xpowi, xhighprSq);
                    BigDecimal c = DivideRound(MultiplyRound(xpowi, ifacN),
                        ifacD.Multiply(BigInteger.ValueOf((2*i + 1))));
                    resul = resul.Add(c);
                    if (System.Math.Abs(c.ToDouble()) < 0.1*eps)
                        break;
                }
                var mc = new MathContext(ErrorToPrecision(resul.ToDouble(), eps));
                return resul.Round(mc);
            }
        }
Beispiel #23
0
        public static BigDecimal Tan(BigDecimal x)
        {
            if (x.CompareTo(BigDecimal.Zero) == 0)
                return BigDecimal.Zero;
            if (x.CompareTo(BigDecimal.Zero) < 0) {
                return Tan(x.Negate()).Negate();
            }
            /* reduce modulo pi
                        */
            BigDecimal res = ModPi(x);

            /* absolute error in the result is err(x)/cos^2(x) to lowest order
                        */
            double xDbl = res.ToDouble();
            double xUlpDbl = x.Ulp().ToDouble()/2d;
            double eps = xUlpDbl/2d/System.Math.Pow(System.Math.Cos(xDbl), 2d);

            if (xDbl > 0.8) {
                /* tan(x) = 1/cot(x) */
                BigDecimal co = Cot(x);
                var mc = new MathContext(ErrorToPrecision(1d/co.ToDouble(), eps));
                return BigDecimal.One.Divide(co, mc);
            } else {
                BigDecimal xhighpr = ScalePrecision(res, 2);
                BigDecimal xhighprSq = MultiplyRound(xhighpr, xhighpr);

                BigDecimal resul = xhighpr.Plus();

                /* x^(2i+1) */
                BigDecimal xpowi = xhighpr;

                var b = new Bernoulli();

                /* 2^(2i) */
                BigInteger fourn = BigInteger.ValueOf(4);
                /* (2i)! */
                BigInteger fac = BigInteger.ValueOf(2);

                for (int i = 2;; i++) {
                    Rational f = b[2*i].Abs();
                    fourn = fourn.ShiftLeft(2);
                    fac = fac.Multiply(BigInteger.ValueOf((2*i))).Multiply(BigInteger.ValueOf((2*i - 1)));
                    f = f.Multiply(fourn).Multiply(fourn.Subtract(BigInteger.One)).Divide(fac);
                    xpowi = MultiplyRound(xpowi, xhighprSq);
                    BigDecimal c = MultiplyRound(xpowi, f);
                    resul = resul.Add(c);
                    if (System.Math.Abs(c.ToDouble()) < 0.1*eps)
                        break;
                }
                var mc = new MathContext(ErrorToPrecision(resul.ToDouble(), eps));
                return resul.Round(mc);
            }
        }
Beispiel #24
0
        public static BigDecimal Sqrt(BigDecimal x, MathContext mc)
        {
            if (x.CompareTo(BigDecimal.Zero) < 0)
                throw new ArithmeticException("negative argument " + x + " of square root");

            if (x.Abs().Subtract(new BigDecimal(System.Math.Pow(10d, -mc.Precision))).CompareTo(BigDecimal.Zero) < 0)
                return ScalePrecision(BigDecimal.Zero, mc);

            /* start the computation from a double precision estimate */
            var s = new BigDecimal(System.Math.Sqrt(x.ToDouble()), mc);
            BigDecimal half = BigDecimal.ValueOf(2);

            /* increase the local accuracy by 2 digits */
            var locmc = new MathContext(mc.Precision + 2, mc.RoundingMode);

            /* relative accuracy requested is 10^(-precision)
                */
            double eps = System.Math.Pow(10.0, -mc.Precision);
            while (true) {
                /* s = s -(s/2-x/2s); test correction s-x/s for being
                        * smaller than the precision requested. The relative correction is 1-x/s^2,
                        * (actually half of this, which we use for a little bit of additional protection).
                        */
                if (System.Math.Abs(BigDecimal.One.Subtract(x.Divide(s.Pow(2, locmc), locmc)).ToDouble()) < eps)
                    break;
                s = s.Add(x.Divide(s, locmc)).Divide(half, locmc);
            }

            return s;
        }
Beispiel #25
0
        public override void Init(IokeObject obj)
        {
            Runtime runtime = obj.runtime;

            obj.Kind        = "Number Decimal";
            runtime.Decimal = obj;

            obj.RegisterMethod(runtime.NewNativeMethod("returns true if the left hand side decimal is equal to the right hand side decimal.",
                                                       new TypeCheckingNativeMethod("==", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(runtime.Decimal)
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                Decimal d    = (Decimal)IokeObject.dataOf(on);
                object other = args[0];
                return(((other is IokeObject) &&
                        (IokeObject.dataOf(other) is Decimal) &&
                        ((on == context.runtime.Decimal && other == on) ||
                         d.value.Equals(((Decimal)IokeObject.dataOf(other)).value))) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Returns a text representation of the object",
                                                       new TypeCheckingNativeMethod.WithNoArguments("asText", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                return(runtime.NewText(on.ToString()));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the square root of the receiver. this should return the same result as calling ** with 0.5",
                                                       new TypeCheckingNativeMethod.WithNoArguments("sqrt", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                BigDecimal value = ((Decimal)IokeObject.dataOf(on)).value;

                if (value.CompareTo(BigDecimal.ZERO) < 1)
                {
                    IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                                 message,
                                                                                 context,
                                                                                 "Error",
                                                                                 "Arithmetic"), context).Mimic(message, context);
                    condition.SetCell("message", message);
                    condition.SetCell("context", context);
                    condition.SetCell("receiver", on);

                    context.runtime.ErrorCondition(condition);
                }

                return(runtime.NewDecimal(new BigSquareRoot().Get(value)));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a text inspection of the object",
                                                           new TypeCheckingNativeMethod.WithNoArguments("inspect", obj,
                                                                                                        (method, on, args, keywords, context, message) => {
                return(method.runtime.NewText(Decimal.GetInspect(on)));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a brief text inspection of the object",
                                                           new TypeCheckingNativeMethod.WithNoArguments("notice", obj,
                                                                                                        (method, on, args, keywords, context, message) => {
                return(method.runtime.NewText(Decimal.GetInspect(on)));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a hash for the decimal number",
                                                           new NativeMethod.WithNoArguments("hash", (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                return(context.runtime.NewNumber(Decimal.GetValue(on).GetHashCode()));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("compares this number against the argument, true if this number is the same, otherwise false",
                                                       new TypeCheckingNativeMethod("==", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                object arg = args[0];
                if (IokeObject.dataOf(arg) is Number)
                {
                    return((Decimal.GetValue(on).CompareTo(Number.GetValue(arg).AsBigDecimal()) == 0) ? context.runtime.True : context.runtime.False);
                }
                else if (IokeObject.dataOf(arg) is Decimal)
                {
                    return((Decimal.GetValue(on).CompareTo(Decimal.GetValue(arg)) == 0) ? context.runtime.True : context.runtime.False);
                }
                else
                {
                    return(context.runtime.False);
                }
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("compares this number against the argument, returning -1, 0 or 1 based on which one is larger. if the argument is a rational, it will be converted into a form suitable for comparing against a decimal, and then compared. if the argument is neither a Rational nor a Decimal, it tries to call asDecimal, and if that doesn't work it returns nil.",
                                                       new TypeCheckingNativeMethod("<=>", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                object arg    = args[0];
                IokeData data = IokeObject.dataOf(arg);

                if (data is Number)
                {
                    return(context.runtime.NewNumber(Decimal.GetValue(on).CompareTo(Number.GetValue(arg).AsBigDecimal())));
                }
                else
                {
                    if (!(data is Decimal))
                    {
                        arg = IokeObject.ConvertToDecimal(arg, message, context, false);
                        if (!(IokeObject.dataOf(arg) is Decimal))
                        {
                            // Can't compare, so bail out
                            return(context.runtime.nil);
                        }
                    }

                    if (on == context.runtime.Decimal || arg == context.runtime.Decimal)
                    {
                        if (arg == on)
                        {
                            return(context.runtime.NewNumber(0));
                        }
                        return(context.runtime.nil);
                    }

                    return(context.runtime.NewNumber(Decimal.GetValue(on).CompareTo(Decimal.GetValue(arg))));
                }
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the difference between this number and the argument. if the argument is a rational, it will be converted into a form suitable for subtracting against a decimal, and then subtracted. if the argument is neither a Rational nor a Decimal, it tries to call asDecimal, and if that fails it signals a condition.",
                                                       new TypeCheckingNativeMethod("-", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("subtrahend")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                object arg = args[0];

                IokeData data = IokeObject.dataOf(arg);

                if (data is Number)
                {
                    return(context.runtime.NewDecimal(Decimal.GetValue(on).subtract(Number.GetValue(arg).AsBigDecimal())));
                }
                else
                {
                    if (!(data is Decimal))
                    {
                        arg = IokeObject.ConvertToDecimal(arg, message, context, true);
                    }

                    return(context.runtime.NewDecimal(Decimal.GetValue(on).subtract(Decimal.GetValue(arg))));
                }
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the sum of this number and the argument. if the argument is a rational, it will be converted into a form suitable for addition against a decimal, and then added. if the argument is neither a Rational nor a Decimal, it tries to call asDecimal, and if that fails it signals a condition.",
                                                       new TypeCheckingNativeMethod("+", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("addend")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                object arg    = args[0];
                IokeData data = IokeObject.dataOf(arg);

                if (data is Number)
                {
                    return(context.runtime.NewDecimal(Decimal.GetValue(on).add(Number.GetValue(arg).AsBigDecimal())));
                }
                else
                {
                    if (!(data is Decimal))
                    {
                        arg = IokeObject.ConvertToDecimal(arg, message, context, true);
                    }

                    return(context.runtime.NewDecimal(Decimal.GetValue(on).add(Decimal.GetValue(arg))));
                }
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the product of this number and the argument. if the argument is a rational, the receiver will be converted into a form suitable for multiplying against a decimal, and then multiplied. if the argument is neither a Rational nor a Decimal, it tries to call asDecimal, and if that fails it signals a condition.",
                                                       new TypeCheckingNativeMethod("*", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("multiplier")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                object arg = args[0];

                IokeData data = IokeObject.dataOf(arg);

                if (data is Number)
                {
                    return(context.runtime.NewDecimal(Decimal.GetValue(on).multiply(Number.GetValue(arg).AsBigDecimal())));
                }
                else
                {
                    if (!(data is Decimal))
                    {
                        arg = IokeObject.ConvertToDecimal(arg, message, context, true);
                    }

                    return(context.runtime.NewDecimal(Decimal.GetValue(on).multiply(Decimal.GetValue(arg))));
                }
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns this number to the power of the argument (which has to be an integer)",
                                                       new TypeCheckingNativeMethod("**", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("exponent")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                object arg    = args[0];
                IokeData data = IokeObject.dataOf(arg);

                if (!(data is Number))
                {
                    arg = IokeObject.ConvertToRational(arg, message, context, true);
                }
                return(context.runtime.NewDecimal(Decimal.GetValue(on).pow(Number.IntValue(arg).intValue())));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the quotient of this number and the argument.",
                                                       new TypeCheckingNativeMethod("/", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("divisor")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                object arg    = args[0];
                IokeData data = IokeObject.dataOf(arg);

                if (data is Number)
                {
                    return(context.runtime.NewDecimal(Decimal.GetValue(on).divide(Number.GetValue(arg).AsBigDecimal())));
                }
                else
                {
                    if (!(data is Decimal))
                    {
                        arg = IokeObject.ConvertToDecimal(arg, message, context, true);
                    }

                    while (Decimal.GetValue(arg).CompareTo(BigDecimal.ZERO) == 0)
                    {
                        IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                                     message,
                                                                                     context,
                                                                                     "Error",
                                                                                     "Arithmetic",
                                                                                     "DivisionByZero"), context).Mimic(message, context);
                        condition.SetCell("message", message);
                        condition.SetCell("context", context);
                        condition.SetCell("receiver", on);

                        object[] newCell = new object[] { arg };

                        context.runtime.WithRestartReturningArguments(() => { context.runtime.ErrorCondition(condition); },
                                                                      context,
                                                                      new IokeObject.UseValue("newValue", newCell));
                        arg = newCell[0];
                    }

                    BigDecimal result = null;
                    try {
                        result = Decimal.GetValue(on).divide(Decimal.GetValue(arg), BigDecimal.ROUND_UNNECESSARY);
                    } catch (System.ArithmeticException) {
                        result = Decimal.GetValue(on).divide(Decimal.GetValue(arg), MathContext.DECIMAL128);
                    }
                    return(context.runtime.NewDecimal(result));
                }
            })));
        }
Beispiel #26
0
        public int CompareTo(Number number)
        {
            if (Equals(this, number))
            {
                return(0);
            }

            // If this is a non-infinity number
            if (numberState == 0)
            {
                // If both values can be represented by a long value
                if (CanBeLong && number.CanBeLong)
                {
                    // Perform a long comparison check,
                    if (longRepresentation > number.longRepresentation)
                    {
                        return(1);
                    }
                    if (longRepresentation < number.longRepresentation)
                    {
                        return(-1);
                    }
                    return(0);
                }

                // And the compared number is non-infinity then use the BigDecimal
                // compareTo method.
                if (number.numberState == 0)
                {
                    return(bigDecimal.CompareTo(number.bigDecimal));
                }

                // Comparing a regular number with a NaN number.
                // If positive infinity or if NaN
                if (number.numberState == NumberState.PositiveInfinity ||
                    number.numberState == NumberState.NotANumber)
                {
                    return(-1);
                }
                // If negative infinity
                if (number.numberState == NumberState.NegativeInfinity)
                {
                    return(1);
                }
                throw new ApplicationException("Unknown number state.");
            }

            // This number is a NaN number.
            // Are we comparing with a regular number?
            if (number.numberState == 0)
            {
                // Yes, negative infinity
                if (numberState == NumberState.NegativeInfinity)
                {
                    return(-1);
                }

                // positive infinity or NaN
                if (numberState == NumberState.PositiveInfinity ||
                    numberState == NumberState.NotANumber)
                {
                    return(1);
                }

                throw new ApplicationException("Unknown number state.");
            }

            // Comparing NaN number with a NaN number.
            // This compares -Inf less than Inf and NaN and NaN greater than
            // Inf and -Inf.  -Inf < Inf < NaN
            return(numberState - number.numberState);
        }
Beispiel #27
0
        ///***
        // * Creates {@code H} of size {@code m x m} as described in [1] (see above).
        // *
        // * @param d statistic
        // * @return H matrix
        // * @throws NumberIsTooLargeException if fractional part is greater than 1
        // * @throws FractionConversionException if algorithm fails to convert
        // * {@code h} to a {@link org.apache.commons.math3.fraction.BigFraction} in
        // * expressing {@code d} as {@code (k - h) / m} for integer {@code k, m} and
        // * {@code 0 <= h < 1}.
        // */
        private BigDecimal[,] createH(double d)
        {
            int    k       = (int)Math.Ceiling(n * d);
            int    m       = 2 * k - 1;
            double hDouble = k - n * d;

            if (hDouble >= 1)
            {
                throw new Exception("Value to large: " + hDouble);
            }
            BigDecimal h = hDouble;


            BigDecimal[,] Hdata = new BigDecimal[m, m];
            ///*
            // * Start by filling everything with either 0 or 1.
            // */
            for (int i = 0; i < m; ++i)
            {
                for (int j = 0; j < m; ++j)
                {
                    if (i - j + 1 < 0)
                    {
                        Hdata[i, j] = 0.0;
                    }
                    else
                    {
                        Hdata[i, j] = 1.0;
                    }
                }
            }
            ///*
            // * Setting up power-array to avoid calculating the same value twice:
            // * hPowers[0] = h^1 ... hPowers[m-1] = h^m
            // */
            BigDecimal[] hPowers = new BigDecimal[m];
            hPowers[0] = h;
            for (int i = 1; i < m; ++i)
            {
                hPowers[i] = h * (hPowers[i - 1]);
            }
            ///*
            // * First column and last row has special values (each other reversed).
            // */
            for (int i = 0; i < m; ++i)
            {
                Hdata[i, 0]     = Hdata[i, 0] - (hPowers[i]);
                Hdata[m - 1, i] = Hdata[m - 1, i] - (hPowers[m - i - 1]);
            }
            ///*
            // * [1] states: "For 1/2 < h < 1 the bottom left element of the matrix
            // * should be (1 - 2*h^m + (2h - 1)^m )/m!" Since 0 <= h < 1, then if h >
            // * 1/2 is sufficient to check:
            // */
            if (h.CompareTo(0.5) == 1)
            {
                Hdata[m - 1, 0] = Hdata[m - 1, 0] + ToolsMathBigDecimal.Pow((h * 2) - 1, m);
            }

            ///*
            // * Aside from the first column and last row, the (i, j)-th element is
            // * 1/(i - j + 1)! if i - j + 1 >= 0, else 0. 1's and 0's are already
            // * put, so only division with (i - j + 1)! is needed in the elements
            // * that have 1's. There is no need to calculate (i - j + 1)! and then
            // * divide - small steps avoid overflows.
            // *
            // * Note that i - j + 1 > 0 <=> i + 1 > j instead of j'ing all the way to
            // * m. Also note that it is started at g = 2 because dividing by 1 isn't
            // * really necessary.
            // */
            for (int i = 0; i < m; ++i)
            {
                for (int j = 0; j < i + 1; ++j)
                {
                    if (i - j + 1 > 0)
                    {
                        for (int g = 2; g <= i - j + 1; ++g)
                        {
                            Hdata[i, j] = Hdata[i, j] / g;
                        }
                    }
                }
            }
            return(Hdata);
        }
Beispiel #28
0
        public static BigDecimal Log(BigDecimal x)
        {
            /* the value is undefined if x is negative.
                */
            if (x.CompareTo(BigDecimal.Zero) < 0)
                throw new ArithmeticException("Cannot take log of negative " + x);
            if (x.CompareTo(BigDecimal.One) == 0) {
                /* log 1. = 0. */
                return ScalePrecision(BigDecimal.Zero, x.Precision - 1);
            }
            if (System.Math.Abs(x.ToDouble() - 1.0) <= 0.3) {
                /* The standard Taylor series around x=1, z=0, z=x-1. Abramowitz-Stegun 4.124.
                        * The absolute error is err(z)/(1+z) = err(x)/x.
                        */
                BigDecimal z = ScalePrecision(x.Subtract(BigDecimal.One), 2);
                BigDecimal zpown = z;
                double eps = 0.5*x.Ulp().ToDouble()/System.Math.Abs(x.ToDouble());
                BigDecimal resul = z;
                for (int k = 2;; k++) {
                    zpown = MultiplyRound(zpown, z);
                    BigDecimal c = DivideRound(zpown, k);
                    if (k%2 == 0)
                        resul = resul.Subtract(c);
                    else
                        resul = resul.Add(c);
                    if (System.Math.Abs(c.ToDouble()) < eps)
                        break;
                }
                var mc = new MathContext(ErrorToPrecision(resul.ToDouble(), eps));
                return resul.Round(mc);
            } else {
                double xDbl = x.ToDouble();
                double xUlpDbl = x.Ulp().ToDouble();

                /* Map log(x) = log root[r](x)^r = r*log( root[r](x)) with the aim
                        * to move roor[r](x) near to 1.2 (that is, below the 0.3 appearing above), where log(1.2) is roughly 0.2.
                        */
                var r = (int) (System.Math.Log(xDbl)/0.2);

                /* Since the actual requirement is a function of the value 0.3 appearing above,
                        * we avoid the hypothetical case of endless recurrence by ensuring that r >= 2.
                        */
                r = System.Math.Max(2, r);

                /* Compute r-th root with 2 additional digits of precision
                        */
                BigDecimal xhighpr = ScalePrecision(x, 2);
                BigDecimal resul = Root(r, xhighpr);
                resul = Log(resul).Multiply(new BigDecimal(r));

                /* error propagation: log(x+errx) = log(x)+errx/x, so the absolute error
                        * in the result equals the relative error in the input, xUlpDbl/xDbl .
                        */
                var mc = new MathContext(ErrorToPrecision(resul.ToDouble(), xUlpDbl/xDbl));
                return resul.Round(mc);
            }
        }
Beispiel #29
0
        public static BigDecimal Sin(BigDecimal x)
        {
            if (x.CompareTo(BigDecimal.Zero) < 0)
                return Sin(x.Negate()).Negate();
            if (x.CompareTo(BigDecimal.Zero) == 0)
                return BigDecimal.Zero;
            /* reduce modulo 2pi
                        */
            BigDecimal res = Mod2Pi(x);
            double errpi = 0.5*System.Math.Abs(x.Ulp().ToDouble());
            var mc = new MathContext(2 + ErrorToPrecision(3.14159, errpi));
            BigDecimal p = PiRound(mc);
            mc = new MathContext(x.Precision);
            if (res.CompareTo(p) > 0) {
                /* pi<x<=2pi: sin(x)= - sin(x-pi)
                                */
                return Sin(SubtractRound(res, p)).Negate();
            }
            if (res.Multiply(BigDecimal.ValueOf(2)).CompareTo(p) > 0) {
                /* pi/2<x<=pi: sin(x)= sin(pi-x)
                                */
                return Sin(SubtractRound(p, res));
            }
            /* for the range 0<=x<Pi/2 one could use sin(2x)=2sin(x)cos(x)
                                * to split this further. Here, use the sine up to pi/4 and the cosine higher up.
                                */
            if (res.Multiply(BigDecimal.ValueOf(4)).CompareTo(p) > 0) {
                /* x>pi/4: sin(x) = cos(pi/2-x)
                                        */
                return Cos(SubtractRound(p.Divide(BigDecimal.ValueOf(2)), res));
            }
            /* Simple Taylor expansion, sum_{i=1..infinity} (-1)^(..)res^(2i+1)/(2i+1)! */
            BigDecimal resul = res;

            /* x^i */
            BigDecimal xpowi = res;

            /* 2i+1 factorial */
            BigInteger ifac = BigInteger.One;

            /* The error in the result is set by the error in x itself.
                                        */
            double xUlpDbl = res.Ulp().ToDouble();

            /* The error in the result is set by the error in x itself.
                                        * We need at most k terms to squeeze x^(2k+1)/(2k+1)! below this value.
                                        * x^(2k+1) < x.ulp; (2k+1)*log10(x) < -x.precision; 2k*log10(x)< -x.precision;
                                        * 2k*(-log10(x)) > x.precision; 2k*log10(1/x) > x.precision
                                        */
            int k = (int) (res.Precision/System.Math.Log10(1.0/res.ToDouble()))/2;
            var mcTay = new MathContext(ErrorToPrecision(res.ToDouble(), xUlpDbl/k));
            for (int i = 1;; i++) {
                /* TBD: at which precision will 2*i or 2*i+1 overflow?
                                                */
                ifac = ifac.Multiply(BigInteger.ValueOf(2*i));
                ifac = ifac.Multiply(BigInteger.ValueOf((2*i + 1)));
                xpowi = xpowi.Multiply(res).Multiply(res).Negate();
                BigDecimal corr = xpowi.Divide(new BigDecimal(ifac), mcTay);
                resul = resul.Add(corr);
                if (corr.Abs().ToDouble() < 0.5*xUlpDbl)
                    break;
            }
            /* The error in the result is set by the error in x itself.
                                        */
            mc = new MathContext(res.Precision);
            return resul.Round(mc);
        }
Beispiel #30
0
        public static BigDecimal Sqrt(BigDecimal x)
        {
            if (x.CompareTo(BigDecimal.Zero) < 0)
                throw new ArithmeticException("negative argument " + x + " of square root");

            return Root(2, x);
        }
Beispiel #31
0
 public int CompareTo(RealNumber other)
 {
     return(Value.CompareTo(other.Value));
 }
Beispiel #32
0
        public static BigDecimal Pow(BigDecimal x, BigDecimal y)
        {
            if (x.CompareTo(BigDecimal.Zero) < 0)
                throw new ArithmeticException("Cannot power negative " + x);
            if (x.CompareTo(BigDecimal.Zero) == 0)
                return BigDecimal.Zero;
            /* return x^y = exp(y*log(x)) ;
                        */
            BigDecimal logx = Log(x);
            BigDecimal ylogx = y.Multiply(logx);
            BigDecimal resul = Exp(ylogx);

            /* The estimation of the relative error in the result is |log(x)*err(y)|+|y*err(x)/x|
                        */
            double errR = System.Math.Abs(logx.ToDouble())*y.Ulp().ToDouble()/2d
                          + System.Math.Abs(y.ToDouble()*x.Ulp().ToDouble()/2d/x.ToDouble());
            var mcR = new MathContext(ErrorToPrecision(1.0, errR));
            return resul.Round(mcR);
        }
Beispiel #33
0
 protected override int UnsafeCompareTo(Dynamic other)
 {
     return(value.CompareTo(other.AsBigDecimal));
 }
Beispiel #34
0
        public static BigDecimal PowRound(BigDecimal x, Rational q)
        {
            /** Special cases: x^1=x and x^0 = 1
                */
            if (q.CompareTo(BigInteger.One) == 0)
                return x;
            if (q.Sign == 0)
                return BigDecimal.One;
            if (q.IsInteger) {
                /* We are sure that the denominator is positive here, because normalize() has been
                        * called during constrution etc.
                        */
                return PowRound(x, q.Numerator);
            }
            /* Refuse to operate on the general negative basis. The integer q have already been handled above.
                        */
            if (x.CompareTo(BigDecimal.Zero) < 0)
                throw new ArithmeticException("Cannot power negative " + x);
            if (q.IsIntegerFraction) {
                /* Newton method with first estimate in double precision.
                                * The disadvantage of this first line here is that the result must fit in the
                                * standard range of double precision numbers exponents.
                                */
                double estim = System.Math.Pow(x.ToDouble(), q.ToDouble());
                var res = new BigDecimal(estim);

                /* The error in x^q is q*x^(q-1)*Delta(x).
                                * The relative error is q*Delta(x)/x, q times the relative error of x.
                                */
                var reserr = new BigDecimal(0.5*q.Abs().ToDouble()
                                            *x.Ulp().Divide(x.Abs(), MathContext.Decimal64).ToDouble());

                /* The main point in branching the cases above is that this conversion
                                * will succeed for numerator and denominator of q.
                                */
                int qa = q.Numerator.ToInt32();
                int qb = q.Denominator.ToInt32();

                /* Newton iterations. */
                BigDecimal xpowa = PowRound(x, qa);
                for (;;) {
                    /* numerator and denominator of the Newton term.  The major
                                        * disadvantage of this implementation is that the updates of the powers
                                        * of the new estimate are done in full precision calling BigDecimal.pow(),
                                        * which becomes slow if the denominator of q is large.
                                        */
                    BigDecimal nu = res.Pow(qb).Subtract(xpowa);
                    BigDecimal de = MultiplyRound(res.Pow(qb - 1), q.Denominator);

                    /* estimated correction */
                    BigDecimal eps = nu.Divide(de, MathContext.Decimal64);

                    BigDecimal err = res.Multiply(reserr, MathContext.Decimal64);
                    int precDiv = 2 + ErrorToPrecision(eps, err);
                    if (precDiv <= 0) {
                        /* The case when the precision is already reached and any precision
                                                * will do. */
                        eps = nu.Divide(de, MathContext.Decimal32);
                    } else {
                        eps = nu.Divide(de, new MathContext(precDiv));
                    }

                    res = SubtractRound(res, eps);
                    /* reached final precision if the relative error fell below reserr,
                                        * |eps/res| < reserr
                                        */
                    if (eps.Divide(res, MathContext.Decimal64).Abs().CompareTo(reserr) < 0) {
                        /* delete the bits of extra precision kept in this
                                                * working copy.
                                                */
                        return res.Round(new MathContext(ErrorToPrecision(reserr.ToDouble())));
                    }
                }
            }
            /* The error in x^q is q*x^(q-1)*Delta(x) + Delta(q)*x^q*log(x).
                                * The relative error is q/x*Delta(x) + Delta(q)*log(x). Convert q to a floating point
                                * number such that its relative error becomes negligible: Delta(q)/q << Delta(x)/x/log(x) .
                                */
            int precq = 3 + ErrorToPrecision((x.Ulp().Divide(x, MathContext.Decimal64)).ToDouble()
                                             /System.Math.Log(x.ToDouble()));

            /* Perform the actual calculation as exponentiation of two floating point numbers.
                                */
            return Pow(x, q.ToBigDecimal(new MathContext(precq)));
        }
Beispiel #35
0
 /// <summary>
 /// Compares the value of this AseDecimal with the AseDecimal value.
 /// </summary>
 public int CompareTo(AseDecimal value)
 {
     return(Backing.CompareTo(value.Backing));
 }
Beispiel #36
0
        public static BigDecimal Root(int n, BigDecimal x)
        {
            if (x.CompareTo(BigDecimal.Zero) < 0)
                throw new ArithmeticException("negative argument " + x + " of root");
            if (n <= 0)
                throw new ArithmeticException("negative power " + n + " of root");

            if (n == 1)
                return x;

            /* start the computation from a double precision estimate */
            var s = new BigDecimal(System.Math.Pow(x.ToDouble(), 1.0/n));

            /* this creates nth with nominal precision of 1 digit
                */
            var nth = new BigDecimal(n);

            /* Specify an internal accuracy within the loop which is
                * slightly larger than what is demanded by 'eps' below.
                */
            BigDecimal xhighpr = ScalePrecision(x, 2);
            var mc = new MathContext(2 + x.Precision);

            /* Relative accuracy of the result is eps.
                */
            double eps = x.Ulp().ToDouble()/(2*n*x.ToDouble());
            for (;;) {
                /* s = s -(s/n-x/n/s^(n-1)) = s-(s-x/s^(n-1))/n; test correction s/n-x/s for being
                        * smaller than the precision requested. The relative correction is (1-x/s^n)/n,
                        */
                BigDecimal c = xhighpr.Divide(s.Pow(n - 1), mc);
                c = s.Subtract(c);
                var locmc = new MathContext(c.Precision);
                c = c.Divide(nth, locmc);
                s = s.Subtract(c);
                if (System.Math.Abs(c.ToDouble()/s.ToDouble()) < eps)
                    break;
            }
            return s.Round(new MathContext(ErrorToPrecision(eps)));
        }