コード例 #1
0
        public static MultiPrecision <N> Pow2(MultiPrecision <N> x)
        {
            if (x.IsNaN)
            {
                return(NaN);
            }

            MultiPrecision <N> x_int = Floor(x);

            if (x_int.Exponent >= UIntUtil.UInt32Bits)
            {
                if (x.Sign == Sign.Plus)
                {
                    return(PositiveInfinity);
                }
                else
                {
                    return(Zero);
                }
            }

            Int64 exponent = x_int.mantissa.Value.Last() >> (UIntUtil.UInt32Bits - (int)x_int.Exponent - 1);

            if (x_int.Sign == Sign.Minus)
            {
                exponent = -exponent;
            }

            MultiPrecision <N> x_frac = x - x_int;

            MultiPrecision <N> v = Ln2 * x_frac;

            if (v.IsZero || v.Exponent < int.MinValue)
            {
                return(new MultiPrecision <N>(Sign.Plus, exponent, Mantissa <N> .One, round: false));
            }

            Accumulator <N> a = Accumulator <N> .One, m = new(v.mantissa, (int)v.Exponent), w = m;

            foreach (var t in Accumulator <N> .TaylorTable)
            {
                Accumulator <N> d = w * t;
                if (d.Digits < Length)
                {
                    break;
                }

                a += d;
                w  = Accumulator <N> .RightRoundShift(w *m, Mantissa <N> .Bits - 1);
            }

            (Mantissa <N> n, int sft) = a.Mantissa;

            MultiPrecision <N> y = new(Sign.Plus, exponent - sft + 1, n, round : false);

            return(y);
        }
コード例 #2
0
        private static MultiPrecision <N> SinCurveTaylorApprox(MultiPrecision <N> x)
        {
            MultiPrecision <N> x_abs = Abs(x);
            MultiPrecision <N> x_int = Round(x_abs), x_frac = x_abs - x_int, xpi = x_frac * PI / 2, squa_xpi = xpi * xpi;
            Int64 cycle = x_int.Exponent < UIntUtil.UInt32Bits / 2 ? ((Int64)x_int) % 4 : (Int64)(x_int % 4);

            if ((cycle == 0 || cycle == 2) && x_frac.IsZero)
            {
                return(Zero);
            }

            Accumulator <N> a = Accumulator <N> .One, m = new(squa_xpi.mantissa, squa_xpi.Exponent), w = m;
            Sign            s = Sign.Minus;

            for (int i = (cycle == 0 || cycle == 2) ? 2 : 1; i + 1 < Accumulator <N> .TaylorTable.Count; i += 2)
            {
                Accumulator <N> t = Accumulator <N> .TaylorTable[i];
                Accumulator <N> d = w * t;

                if (s == Sign.Plus)
                {
                    a += d;
                    s  = Sign.Minus;
                }
                else
                {
                    a -= d;
                    s  = Sign.Plus;
                }

                if (d.Digits < Length)
                {
                    break;
                }

                w = Accumulator <N> .MulShift(w, m);
            }

            (Mantissa <N> n, int sft) = a.Mantissa;

            MultiPrecision <N> y;

            if (cycle == 0 || cycle == 2)
            {
                y  = new MultiPrecision <N>((cycle == 0 ^ x.Sign == Sign.Plus) ? Sign.Minus : Sign.Plus, -sft + 1, n, round: false);
                y *= xpi;
            }
            else
            {
                y = new MultiPrecision <N>((cycle == 1 ^ x.Sign == Sign.Plus) ? Sign.Minus : Sign.Plus, -sft + 1, n, round: false);
            }

            return(y);
        }
コード例 #3
0
 public static bool TryParse(string s, out Accumulator <N> result)
 {
     try {
         result = Parse(s);
         return(true);
     }
     catch (Exception e) when(e is FormatException || e is OverflowException)
     {
         result = null;
         return(false);
     }
 }
コード例 #4
0
        private static ReadOnlyCollection <Accumulator <N> > GenerateTaylorTable()
        {
            List <Accumulator <N> > table = new();

            Accumulator <N> v = One, d = 1;

            while (table.Count < 1 || !(table.Last().IsZero))
            {
                table.Add(RightRoundShift(v, TaylorTableShift));
                d += 1;
                v /= d;
            }

            table = table.Take(table.Count - 1).ToList();

            return(table.AsReadOnly());
        }
コード例 #5
0
        public int CompareTo([AllowNull] Accumulator <N> other)
        {
            if (other is null)
            {
                return(1);
            }

            if (this < other)
            {
                return(-1);
            }

            if (this == other)
            {
                return(0);
            }

            return(1);
        }
コード例 #6
0
        private static MultiPrecision <N> CreateInteger(Sign sign, Accumulator <N> acc)
        {
            (Mantissa <N> n, int sft) = acc.Mantissa;

            return(new MultiPrecision <N>(sign, (Int64)Accumulator <N> .Bits - sft - 1, n, round: false));
        }
コード例 #7
0
 public static Accumulator <N> RoundDiv(Accumulator <N> v1, Accumulator <N> v2)
 {
     return(new Accumulator <N>(BigUInt <Double <N> > .RoundDiv(v1.value, v2.value)));
 }
コード例 #8
0
        public static Accumulator <N> MulShift(Accumulator <N> v1, Accumulator <N> v2)
        {
            Accumulator <N> v = new(BigUInt <Double <N> > .Mul(v1.value, v2.value));

            return(RightRoundShift(v, Mantissa <N> .Bits - 1));
        }
コード例 #9
0
        public static (Accumulator <N> div, Accumulator <N> rem) Div(Accumulator <N> v1, Accumulator <N> v2)
        {
            (BigUInt <Double <N> > div, BigUInt <Double <N> > rem) = BigUInt <Double <N> > .Div(v1.value, v2.value);

            return(new Accumulator <N>(div), new Accumulator <N>(rem));
        }
コード例 #10
0
 public static Accumulator <N> Mul(Accumulator <N> v1, Accumulator <N> v2)
 {
     return(new Accumulator <N>(BigUInt <Double <N> > .Mul(v1.value, v2.value)));
 }
コード例 #11
0
 public static Accumulator <N> Sub(Accumulator <N> v1, UInt32 v2)
 {
     return(new Accumulator <N>(BigUInt <Double <N> > .Sub(v1.value, v2)));
 }
コード例 #12
0
        public static MultiPrecision <N> Log2(MultiPrecision <N> x)
        {
            if (!(x >= Zero))
            {
                return(NaN);
            }
            if (x.IsZero)
            {
                return(NegativeInfinity);
            }
            if (x == PositiveInfinity)
            {
                return(PositiveInfinity);
            }
            if (x.mantissa == Mantissa <N> .One)
            {
                return(x.Exponent);
            }

            Accumulator <N> v = new(x.mantissa);

            int sft;

            for (sft = 0; sft < Accumulator <N> .Bits; sft++)
            {
                v *= v;

                if (v.Value[Accumulator <N> .Length - 1] > UIntUtil.UInt32Round)
                {
                    v = Accumulator <N> .RightRoundBlockShift(v, Mantissa <N> .Length);

                    break;
                }
                else
                {
                    v = Accumulator <N> .RightRoundShift(v, Mantissa <N> .Bits - 1);
                }
            }
            if (sft == Accumulator <N> .Bits)
            {
                return(x.Exponent);
            }

            UInt32[] mantissa = new UInt32[Mantissa <N> .Length];
            UInt32   m        = 1;

            for (int i = mantissa.Length - 1; i >= 0; i--)
            {
                for (int j = (i < mantissa.Length - 1) ? 0 : 1; j < UIntUtil.UInt32Bits; j++)
                {
                    v  *= v;
                    m <<= 1;

                    if (v.Value[Accumulator <N> .Length - 1] > UIntUtil.UInt32Round)
                    {
                        v = Accumulator <N> .RightRoundBlockShift(v, Mantissa <N> .Length);

                        m |= 1u;
                    }
                    else
                    {
                        v = Accumulator <N> .RightRoundShift(v, Mantissa <N> .Bits - 1);
                    }
                }

                mantissa[i] = m;
                m           = 0;
            }

            v *= v;
            bool round = v.Value[Accumulator <N> .Length - 1] > UIntUtil.UInt32Round;

            long intpart = x.Exponent;
            MultiPrecision <N> decpart = new(Sign.Plus, -(Int64)sft - 1, new Mantissa <N>(mantissa, enable_clone: false), round);

            MultiPrecision <N> y = intpart + decpart;

            return(y);
        }