Beispiel #1
0
        private static void getStringRepresentation(IntegerNumber x, int base10Digits, StringBuilder result)
        {
            if (base10Digits <= 18)
            {
                string value = x.ToLong.ToString();
                int    diff  = value.Length - base10Digits;
                if (diff != 0)
                {
                    if (diff < 0)
                    {
                        value = "".PadLeft(-diff, '0') + value;
                    }
                    else
                    {
                        value = value.Remove(0, diff);
                    }
                }
                result.Append(value);
                return;
            }
            int           secondHalfDigits = (base10Digits + 1) / 2;
            IntegerNumber half = IntegerNumber.Pow(10, secondHalfDigits);
            IntegerNumber reminder, quotient = IntegerNumber.DivRem(x, half, out reminder);

            getStringRepresentation(quotient, base10Digits - secondHalfDigits, result);
            getStringRepresentation(reminder, secondHalfDigits, result);
        }
Beispiel #2
0
        public IntegerNumber ModPow(IntegerNumber power, IntegerNumber prime, Func <IntegerNumber, IntegerNumber> modPFunction)
        {
            IntegerNumber a = this;

            if (power.IsNegative)
            {
                a     = a.ModInverse(prime);
                power = -power;
            }
            int highestBitPosition = power.Digits * 64 - 1;

            while (highestBitPosition >= 0 && !power.GetBitAt(highestBitPosition))
            {
                highestBitPosition--;
            }
            IntegerNumber result = highestBitPosition < 0 ? One : a;

            for (int i = highestBitPosition; --i >= 0;)
            {
                result = modPFunction(result.Square());
                if (power.GetBitAt(i))
                {
                    result = modPFunction(result * a);
                }
            }
            var diff = result - prime;

            return(diff.IsNegative ? result : diff);
        }
Beispiel #3
0
        public static IntegerNumber DivRem(IntegerNumber number, long digit, out long remainder)
        {
            IntegerNumber result = new IntegerNumber(number.bits, true);

            remainder = (long)AsmX64Operations.DivideDigit(result.bits, (ulong)digit, result.Digits, true);
            return(result);
        }
Beispiel #4
0
        public IntegerNumber Inverse()
        {
            shrink(this);
            IntegerNumber remainder, result = Inverse(this, out remainder);

            return(result);
        }
Beispiel #5
0
        public static IntegerNumber operator /(IntegerNumber number1, long number2)
        {
            long          remainder;
            IntegerNumber quotient = IntegerNumber.DivRem(number1, number2, out remainder);

            return(quotient);
        }
Beispiel #6
0
        public override string ToString()
        {
            IntegerNumber x        = this;
            bool          negative = x.IsNegative;

            if (negative)
            {
                x = -x;
            }
            StringBuilder result = new StringBuilder();

            getStringRepresentation(x, Math.Max(1, (int)Math.Ceiling(x.BitsCount * LOG10_2)), result);
            int lowzeros = 0;

            while (lowzeros + 1 < result.Length && result[lowzeros] == '0')
            {
                lowzeros++;
            }
            if (lowzeros > 0)
            {
                result = result.Remove(0, lowzeros);
            }
            if (negative)
            {
                result = result.Insert(0, '-');
            }
            return(result.ToString());
        }
Beispiel #7
0
        public static IntegerNumber operator *(IntegerNumber number1, IntegerNumber number2)
        {
            IntegerNumber source1 = number1.ExtendTo(number2.Digits);
            IntegerNumber source2 = number2.ExtendTo(number1.Digits);

            ulong[] result = new ulong[source1.Digits * 2];
            AsmX64Operations.FastestMultiplication(source1.bits, source2.bits, result, source1.Digits, true);
            return(new IntegerNumber(result, false));
        }
Beispiel #8
0
        public static void shrink(IntegerNumber number)
        {
            int digits = number.RealDigits;

            if (digits != number.Digits)
            {
                Array.Resize(ref number.bits, digits);
            }
        }
Beispiel #9
0
        //f[x_] := x^2 - y
        //FullSimplify[x - f[x] / D[f[x], x]] = (x + y / x) / 2  [Newton method]
        //FullSimplify[x - 2*f[x]*D[f[x], x]/(2*D[f[x], x]^2 - f[x]*D[f[x], {x, 2}])] = x * (x^2 + 3 y) / (3 x^2 + y) [Halley]
        //In practice Newton method is faster than Halley 3'rd order convergence for SQRT.
        public IntegerNumber Sqrt()
        {
            if (this.IsNegative)
            {
                throw new ArithmeticException("NaN");
            }
            if (this.IsZero)
            {
                return(IntegerNumber.Zero);
            }
            shrink(this);
            int n = this.Digits;
            int computedDigits = (n & 1) != 0 ? 1 : 2;

            if (computedDigits + 2 <= n)
            {
                computedDigits += 2;
            }

            ulong[]       inputBits  = this.bits;
            IntegerNumber t          = this.GetDigits(n - computedDigits, computedDigits, true);
            double        estimate   = Math.Sqrt(t.ToDouble);
            double        highDouble = Math.Floor(estimate / Power2_64);
            double        lowDouble  = estimate - highDouble * Power2_64;
            IntegerNumber root       = new IntegerNumber(new ulong[] { (ulong)lowDouble, (ulong)highDouble }, false);

            if (root.IsNegative)
            {
                Array.Resize(ref root.bits, 3);
            }
            while (true)
            {
                IntegerNumber oldRoot = root;
                root = (root + t / root) >> 1;
                if (IntegerNumber.Abs(oldRoot - root) <= IntegerNumber.One)
                {
                    break;
                }
            }
            int additionalDigits = 1;

            for (int i = computedDigits; i < n + additionalDigits;)
            {
                int digits = Math.Min(computedDigits, n - computedDigits + 1) >> 1;
                i              += computedDigits;
                root          <<= digits * 64;
                computedDigits += digits * 2;
                t               = computedDigits >= n ? this : this.GetDigits(n - computedDigits, computedDigits, true);
                root            = (root + t / root) >> 1;
            }
            IntegerNumber square = root.Square();

            return(this >= square ? root : root - IntegerNumber.One);
        }
Beispiel #10
0
        public static IntegerNumber operator -(IntegerNumber number1, IntegerNumber number2)
        {
            if (number1.IsNegative != number2.IsNegative)
            {
                return(number2.IsZero ? number1 : number1 + (-number2));
            }   //when subtracting numbers with the same sign, the absolute value of the result is less than the absoulute value of each input. (number size decreases).
            IntegerNumber source1 = number1.ExtendTo(number2.Digits);
            IntegerNumber source2 = number2.ExtendTo(number1.Digits);

            ulong[] result = new ulong[source1.Digits];
            AsmX64Operations.Subtract(source1.bits, source2.bits, result, 0, result.Length);
            return(new IntegerNumber(result, false));
        }
Beispiel #11
0
        public static IntegerNumber operator -(IntegerNumber number)
        {
            if (number.bits[number.bits.Length - 1] == SignBit && number.isZero(0, number.bits.Length - 1))
            {   //make positive the highly compact negative numbers - as a special case.
                ulong[] bits = new ulong[number.bits.Length + 1];
                bits[number.bits.Length - 1] = SignBit;
                return(new IntegerNumber(bits, false));
            }
            IntegerNumber result = new IntegerNumber(number.bits, true);

            AsmX64Operations.Negate(result.bits, result.Digits);
            return(result);
        }
Beispiel #12
0
 public IntegerNumber ShanksSqrt(IntegerNumber p, Func <IntegerNumber, IntegerNumber> modPFunction)
 {
     if (this.ModPow((p - 1) >> 1, p, modPFunction) == (p - 1))
     {
         return(-1);
     }   //No Sqrt Exists
     if ((p.LowestByte & 3) == 3)
     {
         var result = this.ModPow((p + 1) >> 2, p, modPFunction);
         return(result);
     }
     throw new NotImplementedException("Not a special prime modulo.");
 }
Beispiel #13
0
        /// <summary>
        /// return this / n modulo p.
        /// </summary>
        /// <param name="n"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public IntegerNumber DivideModulo(IntegerNumber n, IntegerNumber p)
        {
            if (n.IsZero)
            {
                return(n);
            }
            if (p.IsZero)
            {
                return(p);
            }
            IntegerNumber a = this;   //x * a + u1 * b = n
            IntegerNumber c = 0;      //y * c + u2 * d = p
            IntegerNumber x = n;

            while (p.IsEven)
            {
                p >>= 1;
            }
            IntegerNumber y = p;

            while (x.IsEven)
            {
                x >>= 1;
                a   = a.IsEven ? a >> 1 : (a + p) >> 1;
            }
            while (!x.IsZero)
            {
                while (x.IsEven)
                {
                    x >>= 1;
                    a   = a.IsEven ? a >> 1 : (a + p) >> 1;
                }
                IntegerNumber diff = x - y;
                if (diff.IsNegative)
                {
                    y = x;
                    x = -diff;
                    IntegerNumber temp = a; a = c; c = temp;
                }
                else
                {
                    x = diff;
                }
                a -= c;
                if (a.IsNegative)
                {
                    a += p;
                }
            }
            return(c);
        }
Beispiel #14
0
        public static double Log2(IntegerNumber number)
        {
            if (number.IsNegative)
            {
                throw new InvalidOperationException("Real logarithm of a negative number does not exist.");
            }
            shrink(number);
            int n = number.Digits;

            if (n <= 1)
            {
                return(number.IsZero ? 0.0 : Math.Log(number.HighestDigit) * LG_E);
            }
            return(Math.Log(number.HighestDigit * Power2_64 + number.bits[n - 2]) * LG_E + (n - 2) * 64);
        }
Beispiel #15
0
        public static IntegerNumber operator >>(IntegerNumber x, int shift)
        {
            if (shift == 0)
            {
                return(x);
            }
            if (shift < 0)
            {
                return(x << (-shift));
            }
            IntegerNumber result = new IntegerNumber(x.bits, true);

            AsmX64Operations.IntShr(result.bits, shift, result.Digits, true);
            return(result);
        }
Beispiel #16
0
        public IntegerNumber GetBitsAt(int index, int count)
        {
            IntegerNumber shifted = this >> index;
            int           cell    = count >> 6;
            int           pos     = count & 63;
            IntegerNumber result  = new IntegerNumber(new ulong[cell + 1], false);

            for (int i = Math.Min(cell, shifted.bits.Length); --i >= 0;)
            {
                result.bits[i] = shifted.bits[i];
            }
            if (pos != 0 && cell < shifted.bits.Length)
            {
                result.bits[cell] = shifted.bits[cell] & (ulong.MaxValue >> (64 - pos));
            }
            return(result);
        }
Beispiel #17
0
        public static IntegerNumber operator +(IntegerNumber number1, IntegerNumber number2)
        {
            if (number1.IsNegative != number2.IsNegative)
            {
                return(number2.IsZero ? number1 : number1 - (-number2));
            }
            IntegerNumber source1 = number1.ExtendTo(number2.Digits);
            IntegerNumber source2 = number2.ExtendTo(number1.Digits);

            ulong[] result = new ulong[source1.Digits];
            byte    carry  = AsmX64Operations.Add(source1.bits, source2.bits, result, 0, result.Length);

            if (carry != (byte)(result[result.Length - 1] >> 63))
            {
                Array.Resize(ref result, result.Length + 1);
                result[result.Length - 1] = carry == 0 ? 0UL : ulong.MaxValue;
            }
            return(new IntegerNumber(result, false));
        }
Beispiel #18
0
        public static IntegerNumber Pow(int baseNumber, int exponent)
        {
            int highestBitPosition = BSR((uint)exponent);

            if (highestBitPosition < 0)
            {
                return(IntegerNumber.One);
            }
            IntegerNumber number = new IntegerNumber(baseNumber);
            IntegerNumber result = number;

            for (int i = highestBitPosition; --i >= 0;)
            {
                result = result.Square();
                shrink(result);
                if ((exponent & (1 << i)) != 0)
                {
                    result *= baseNumber;
                }
            }
            return(result);
        }
Beispiel #19
0
        public static IntegerNumber Inverse(IntegerNumber number, out IntegerNumber remainder)
        {
            int n = number.Digits;

            if (n <= IntegerDigitsBreakPoint)
            {
                ulong[] a = new ulong[(n + 1) * 2];
                a[n * 2] = 1UL;
                IntegerNumber b = number.ExtendTo(n + 1);
                ulong[]       q = new ulong[(n + 1) * 2];
                AsmX64Operations.GetDivMod(a, b.bits, n + 1, q, true);
                remainder = new IntegerNumber(a, false);
                shrink(remainder);
                IntegerNumber result = new IntegerNumber(q, false);
                shrink(result);
                return(result);
            }

            bool isNegative = false;

            if (number.IsNegative)
            {
                number     = -number;
                isNegative = true;
                n          = number.Digits;
            }
            //Newton iteration: x <- x + x * (1 - d * x^2)
            int           m = (n + 5) >> 1;
            IntegerNumber dx, dhi = number.GetDigits(n - m, m, false);
            IntegerNumber x = Inverse(dhi, out dx);

            //IntegerNumber test = x * d + dx;
            //shrink(ref test);
            //if (test.Digits != d.Digits * 2 + 1 || test.bits[d.Digits * 2] != 1UL || Enumerable.Range(0, d.Digits * 2).Any(idx => test.bits[idx] != 0UL))
            //{
            //    System.Diagnostics.Debugger.Break();
            //}

            const int     CorrectionDigits = 4;
            IntegerNumber dlo = number.GetDigits(0, n - m, true);

            IntegerNumber dp    = (dx << ((n - m) * 64)) - dlo * x;
            IntegerNumber delta = dp >> ((m - CorrectionDigits) * 64);  //keep one additional correction digit.

            shrink(delta);

            delta  *= x;
            delta >>= (m + CorrectionDigits) * 64;
            shrink(delta);

            x <<= (n - m) * 64;
            x  += delta;

            //FACT: number * x == (IntegerNumber.One << (n * 128)) - ((dp << ((n - m) * 64)) - delta * number);
            //but :     remainder = number * x;
            //then:     Array.Resize(ref remainder.bits, n * 2);
            //then:     shrink(ref remainder);
            //then:     remainder = -remainder;
            remainder = ((dp - delta * dhi) << ((n - m) * 64)) - delta * dlo;
            shrink(remainder);

            int count = 0;

            while (remainder.IsNegative)
            {
                remainder += number;
                x         -= One;
                count++;
                if (count >= 2)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }
            while (remainder >= number)
            {
                remainder -= number;
                x         += One;
                count++;
                if (count >= 2)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }

            if (isNegative)
            {
                x         = -x;
                remainder = -remainder;
            }
            return(x);
        }
Beispiel #20
0
 public static IntegerNumber Abs(IntegerNumber number)
 {
     return(number.IsNegative ? -number : number);
 }
Beispiel #21
0
        public static IntegerNumber DivRem(IntegerNumber dividend, IntegerNumber divisor, out IntegerNumber remainder)
        {
            shrink(dividend);
            shrink(divisor);
            int           dividendDigits = dividend.Digits;
            int           divisorDigits  = divisor.Digits;
            IntegerNumber quotient;
            int           n = Math.Max(divisorDigits, (dividendDigits + 1) >> 1);

            if (divisorDigits <= IntegerDigitsBreakPoint)
            {
                dividend  = dividend.ExtendTo(n * 2);
                divisor   = divisor.ExtendTo(n);
                quotient  = new IntegerNumber(new ulong[n * 2], false);
                remainder = new IntegerNumber(dividend.bits, true);
                AsmX64Operations.GetDivMod(remainder.bits, divisor.bits, n, quotient.bits, true);
                shrink(quotient);
                shrink(remainder);
                return(quotient);
            }
            bool sign = false;

            if (dividend.IsNegative != divisor.IsNegative)
            {
                dividend = IntegerNumber.Abs(dividend);
                divisor  = IntegerNumber.Abs(divisor);
                sign     = true;
            }
            else if (dividend.IsNegative && divisor.IsNegative)
            {
                dividend = -dividend;
                divisor  = -divisor;
            }

            int           delta = n - divisorDigits;
            IntegerNumber x     = (divisor << (delta * 128)).Inverse();

            quotient = dividend * x >> (n * 128);
            shrink(quotient);
            remainder = dividend - quotient * divisor;
            shrink(remainder);
            int count = 0;

            while (remainder.IsNegative)
            {
                remainder += divisor;
                quotient  -= One;
                count++;
                if (count >= 2)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }
            while (remainder >= divisor)
            {
                remainder -= divisor;
                quotient  += One;
                count++;
                if (count >= 2)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }

            if (sign)
            {
                quotient  = -quotient;
                remainder = -remainder;
            }
            return(quotient);
        }
Beispiel #22
0
 public IntegerNumber ModInverse(IntegerNumber p)
 {
     return(One.DivideModulo(this, p));
 }
Beispiel #23
0
        public static bool UnitTest()
        {
            //    SPECIAL prime: 2^64 - 2^32 + 1
            //prime: 2^64 - 2^34 + 1
            //prime: 2^64 - 2^40 + 1
            //    SPECIAL prime: 2 ^ 128 - 2 ^ 54 + 1
            //prime: 2 ^ 128 - 2 ^ 108 + 1
            //prime: 2 ^ 256 - 2 ^ 168 + 1
            //prime: 2 ^ 256 - 2 ^ 174 + 1
            //prime: 2 ^ 512 - 2 ^ 32 + 1
            //prime: 2 ^ 512 - 2 ^ 288 + 1
            //    SPECIAL prime: 2 ^ 1024 - 2 ^ 142 + 1
            //    SPECIAL prime: 2 ^ 1024 - 2 ^ 226 + 1
            //prime: 2 ^ 1024 - 2 ^ 562 + 1
            //prime: 2 ^ 1024 - 2 ^ 718 + 1
            //prime: 2 ^ 1024 - 2 ^ 856 + 1
            //prime: 2 ^ 1024 - 2 ^ 880 + 1
            //prime: 2 ^ 4096 - 2 ^ 3510 + 1
            //prime: 2 ^ 4096 - 2 ^ 3708 + 1
            if ("not exec".Trim() == "exec")
            {
                StringBuilder primes = new StringBuilder();
                for (int exp = 6; exp <= 12; exp++)
                {
                    int shift = 1 << exp;
                    Parallel.For(32, shift, i =>
                    {
                        ulong[] baseValue   = new ulong[shift / 64];
                        ulong[] expValue    = new ulong[shift / 64];
                        ulong[] modulo      = new ulong[shift / 64];
                        ulong[] subtractor  = new ulong[shift / 64];
                        ulong[] one         = new ulong[shift / 64];
                        ulong[] pPlusOne    = new ulong[shift / 64];
                        subtractor[i / 64] |= 1UL << (i & 63);
                        modulo[0]           = 1UL;
                        one[0]              = 1UL;
                        AsmX64Operations.Subtract(modulo, subtractor, modulo, 0, modulo.Length);
                        modulo.CopyTo(expValue, 0);
                        modulo.CopyTo(pPlusOne, 0);
                        expValue[0]--;
                        pPlusOne[0]++;

                        int isPrime = 1;
                        for (int a = 2; a <= 128; a++)
                        {
                            one.CopyTo(baseValue, 0);
                            baseValue[0] = (ulong)a;
                            AsmX64Operations.ModularExponentiation(baseValue, expValue, modulo, modulo.Length, 5);
                            if (Enumerable.Range(0, modulo.Length).All(idx => baseValue[idx] == one[idx]) ||
                                Enumerable.Range(0, modulo.Length).All(idx => baseValue[idx] == pPlusOne[idx]))
                            {
                                continue;
                            }
                            isPrime = 0;
                            break;
                        }

                        if (isPrime != 0)
                        {
                            lock (primes)
                            {
                                primes.AppendLine("prime: 2^" + shift.ToString() + " - 2^" + i.ToString() + " + 1");
                            }
                        }
                    });
                }
                Clipboard.SetText(primes.ToString());
                System.Windows.Forms.MessageBox.Show(primes.ToString(), "message");
            }

            Random     random = new Random(1002);
            BigInteger maxx   = 0;
            BigInteger minn   = 0;
            bool       ok     = true;

            for (int i = 2; --i >= 0;)
            {
                byte[] bytes1 = new byte[112 * 8 + random.Next(32 * 8)];
                byte[] bytes2 = new byte[112 * 8 + random.Next(32 * 8)];
                random.NextBytes(bytes1);
                random.NextBytes(bytes2);

                BigInteger    n1 = new BigInteger(bytes1);
                BigInteger    n2 = new BigInteger(bytes2);
                IntegerNumber f1 = new IntegerNumber(bytes1);
                IntegerNumber f2 = new IntegerNumber(bytes2);
                if (n1.ToString() != f1.ToString())
                {
                    ok = false;
                }
                if (n2.ToString() != f2.ToString())
                {
                    ok = false;
                }

                BigInteger    a1 = n1 + n2;
                IntegerNumber a2 = f1 + f2;
                if (a1.ToString() != a2.ToString())
                {
                    ok = false;
                }

                BigInteger    s1 = n1 - n2;
                IntegerNumber s2 = f1 - f2;
                if (s1.ToString() != s2.ToString())
                {
                    ok = false;
                }

                BigInteger    m1 = n1 * n2;
                IntegerNumber m2 = f1 * f2;
                if (m1.ToString() != m2.ToString())
                {
                    ok = false;
                }

                int           shrvalue = random.Next(256) + 1;
                BigInteger    sh1      = n1 >> shrvalue;
                IntegerNumber sh2      = f1 >> shrvalue;
                if (sh1.ToString() != sh2.ToString())
                {
                    ok = false;
                }
                if ((-f1).ToString() != (-n1).ToString() || (-f2).ToString() != (-n2).ToString())
                {
                    ok = false;
                }

                int           shlvalue = random.Next(256) + 1;
                BigInteger    shl1     = n1 << shlvalue;
                IntegerNumber shl2     = f1 << shlvalue;
                if (shl1.ToString() != shl2.ToString())
                {
                    ok = false;
                }

                byte[] bytesINV = new byte[(192 + 32) * 8 + random.Next(64 * 8)];
                random.NextBytes(bytesINV);
                BigInteger    num1 = new BigInteger(bytesINV);
                IntegerNumber num2 = new IntegerNumber(bytesINV);
                if (num1.ToString() != num2.ToString())
                {
                    ok = false;
                }
                BigInteger    inv0 = (BigInteger.One << (num2.Digits * 64 * 2)) / num1;
                IntegerNumber inv1 = num2.Inverse();
                if (inv0.ToString() != inv1.ToString())
                {
                    ok = false;
                }

                byte[] bytes4 = new byte[bytes1.Length * 4];
                random.NextBytes(bytes4);
                BigInteger    n4  = new BigInteger(bytes4);
                IntegerNumber f4  = new IntegerNumber(bytes4);
                BigInteger    qb4 = n4 / n1;
                IntegerNumber qn4 = f4 / f1;
                if (qb4.ToString() != qn4.ToString())
                {
                    ok = false;
                }
                byte[] bytes3 = new byte[(bytes1.Length + bytes2.Length) & -8];
                random.NextBytes(bytes3);
                BigInteger    square1 = BigInteger.Abs(new BigInteger(bytes3));
                IntegerNumber square2 = IntegerNumber.Abs(new IntegerNumber(bytes3));
                BigInteger    root1   = square1.Sqrt();
                IntegerNumber root2   = square2.Sqrt();
                if (root1.ToString() != root2.ToString())
                {
                    ok = false;
                }
                if (!ok)
                {
                    break;
                }
            }
            return(ok);
        }
Beispiel #24
0
        //InverseSqrt[this] = Sqrt[(this << (this.Digits * 64)).Inverse()]
        //InverseSqrt[this] = Sqrt[(1 << (this.Digits * 192)) / this]
        //f[x_] := (1/x)^2 - y
        //FullSimplify[x - f[x] / D[f[x], x]] = x * (1/2) * (3 - x^2 y)
        public IntegerNumber InverseSqrt()
        {
            if (this.IsNegative || this.IsZero)
            {
                throw new ArithmeticException("NaN");
            }
            shrink(this);
            int n = this.Digits;
            int computedDigits = (n & 1) != 0 ? 1 : 2;

            if (computedDigits + 2 <= n)
            {
                computedDigits += 2;
            }

            ulong[]       inputBits     = this.bits;
            IntegerNumber t             = this.GetDigits(n - computedDigits, computedDigits, true);
            double        estimate      = Math.Pow(Power2_64, computedDigits * 1.5) / Math.Sqrt(t.ToDouble);
            List <ulong>  initialDigits = new List <ulong>();

            while (estimate != 0)
            {
                initialDigits.Add((ulong)Math.IEEERemainder(estimate, Power2_64));
                estimate = Math.Floor(estimate / Power2_64);
            }
            IntegerNumber root  = new IntegerNumber(initialDigits.ToArray(), false);
            IntegerNumber three = new IntegerNumber(3L);
            //repeat iteration once to reach full precision.
            int iterations1 = (int)Math.Ceiling(Math.Log(initialDigits.Count * 64.0 / 52, 2.0));

            for (int step = iterations1; --step >= 0;)
            {
                int shift = computedDigits * 64 * 3;
                root = root * ((three << shift) - root.Square() * t) >> (1 + shift);
                shrink(root);
            }
            if (computedDigits == n)
            {
                return(root);
            }

            int additionalDigits = 2;
            int totalDigits      = n + additionalDigits;

            do
            {
                int digits = Math.Min(Math.Max(computedDigits - 1, 1), totalDigits - computedDigits);
                computedDigits += digits;
                t = this.GetDigits(n - computedDigits, computedDigits, true);

                //root <<= digits * 64;
                //int shift = computedDigits * 3 * 64;
                //root = root * ((three << shift) - root.Square() * t) >> (1 + shift);

                int shift1 = (computedDigits * 3 - digits * 2) * 64;
                int shift2 = (computedDigits * 3 - digits * 3) * 64;
                root = root * ((three << shift1) - root.Square() * t) >> (1 + shift2);

                shrink(root);
            } while (computedDigits < totalDigits);

            root >>= additionalDigits * 64;
            shrink(root);

            return(root);
        }
Beispiel #25
0
        public static IntegerNumber operator %(IntegerNumber number1, IntegerNumber number2)
        {
            IntegerNumber remainder, quotient = IntegerNumber.DivRem(number1, number2, out remainder);

            return(remainder);
        }