Пример #1
0
        private static void MonReduction(int[] Result, BigInteger Modulus, int N2)
        {
            // res + m*modulus_digits
            int[] modulus_digits = Modulus._digits;
            int   modulusLen     = Modulus._numberLength;
            long  outerCarry     = 0;

            for (int i = 0; i < modulusLen; i++)
            {
                long innnerCarry = 0;
                int  m           = (int)Multiplication.UnsignedMultAddAdd(Result[i], N2, 0, 0);
                for (int j = 0; j < modulusLen; j++)
                {
                    innnerCarry   = Multiplication.UnsignedMultAddAdd(m, modulus_digits[j], Result[i + j], (int)innnerCarry);
                    Result[i + j] = (int)innnerCarry;
                    innnerCarry   = IntUtils.URShift(innnerCarry, 32);
                }

                outerCarry            += (Result[i + modulusLen] & 0xFFFFFFFFL) + innnerCarry;
                Result[i + modulusLen] = (int)outerCarry;
                outerCarry             = IntUtils.URShift(outerCarry, 32);
            }

            Result[modulusLen << 1] = (int)outerCarry;

            // res / r
            for (int j = 0; j < modulusLen + 1; j++)
            {
                Result[j] = Result[j + modulusLen];
            }
        }
Пример #2
0
        private static long DivideLongByBillion(long N)
        {
            long quot;
            long rem;

            if (N >= 0)
            {
                long bLong = 1000000000L;
                quot = (N / bLong);
                rem  = (N % bLong);
            }
            else
            {
                /*
                 * Make the dividend positive shifting it right by 1 bit then get
                 * the quotient an remainder and correct them properly
                 */
                long aPos = IntUtils.URShift(N, 1);
                long bPos = IntUtils.URShift(1000000000L, 1);
                quot = aPos / bPos;
                rem  = aPos % bPos;
                // double the remainder and add 1 if 'a' is odd
                rem = (rem << 1) + (N & 1);
            }
            return((rem << 32) | (quot & 0xFFFFFFFFL));
        }
Пример #3
0
        /// <summary>
        /// Returns a new BigInteger whose value is <c>this >> N</c>
        /// <para>For negative arguments, the result is also negative.
        /// The shift distance may be negative which means that this is shifted left.
        /// </para>
        /// </summary>
        ///
        /// <param name="Result">The result</param>
        /// <param name="ResultLen">The result length</param>
        /// <param name="Value">The source BigIntger</param>
        /// <param name="IntCount">The number integers</param>
        /// <param name="N">Shift distance</param>
        ///
        /// <returns>this >> N, if N >= 0; this &lt;&lt; (-n) otherwise</returns>
        internal static bool ShiftRight(int[] Result, int ResultLen, int[] Value, int IntCount, int N)
        {
            int  i;
            bool allZero = true;

            for (i = 0; i < IntCount; i++)
            {
                allZero &= Value[i] == 0;
            }
            if (N == 0)
            {
                Array.Copy(Value, IntCount, Result, 0, ResultLen);
                i = ResultLen;
            }
            else
            {
                int leftShiftCount = 32 - N;

                allZero &= (Value[i] << leftShiftCount) == 0;
                for (i = 0; i < ResultLen - 1; i++)
                {
                    Result[i] = IntUtils.URShift(Value[i + IntCount], N) |
                                (Value[i + IntCount + 1] << leftShiftCount);
                }
                Result[i] = IntUtils.URShift(Value[i + IntCount], N);
                i++;
            }

            return(allZero);
        }
Пример #4
0
        private static int[] Square(int[] X, int XLen, int[] Result)
        {
            long carry;

            for (int i = 0; i < XLen; i++)
            {
                carry = 0;
                for (int j = i + 1; j < XLen; j++)
                {
                    carry         = UnsignedMultAddAdd(X[i], X[j], Result[i + j], (int)carry);
                    Result[i + j] = (int)carry;
                    carry         = IntUtils.URShift(carry, 32);
                }
                Result[i + XLen] = (int)carry;
            }

            BitLevel.ShiftLeftOneBit(Result, Result, XLen << 1);

            carry = 0;
            for (int i = 0, index = 0; i < XLen; i++, index++)
            {
                carry         = UnsignedMultAddAdd(X[i], X[i], Result[index], (int)carry);
                Result[index] = (int)carry;
                carry         = IntUtils.URShift(carry, 32);
                index++;
                carry        += Result[index] & 0xFFFFFFFFL;
                Result[index] = (int)carry;
                carry         = IntUtils.URShift(carry, 32);
            }
            return(Result);
        }
Пример #5
0
        /// <summary>
        /// Performs the same as GcdBinary(BigInteger, BigInteger)}, but with numbers of 63 bits,
        /// represented in positives values of long type.
        /// </summary>
        ///
        /// <param name="X">A positive number</param>
        /// <param name="Y">A positive number></param>
        ///
        /// <returns>Returns <c>Gcd(X, Y)</c></returns>
        internal static long GcdBinary(long X, long Y)
        {
            // (op1 > 0) and (op2 > 0)
            int lsb1      = IntUtils.NumberOfTrailingZeros(X);
            int lsb2      = IntUtils.NumberOfTrailingZeros(Y);
            int pow2Count = System.Math.Min(lsb1, lsb2);

            if (lsb1 != 0)
            {
                X = IntUtils.URShift(X, lsb1);
            }
            if (lsb2 != 0)
            {
                Y = IntUtils.URShift(Y, lsb2);
            }

            do
            {
                if (X >= Y)
                {
                    X -= Y;
                    X  = IntUtils.URShift(X, IntUtils.NumberOfTrailingZeros(X));
                }
                else
                {
                    Y -= X;
                    Y  = IntUtils.URShift(Y, IntUtils.NumberOfTrailingZeros(Y));
                }
            } while (X != 0);

            return(Y << pow2Count);
        }
Пример #6
0
        /// <summary>
        /// A random number is generated until a probable prime number is found
        /// </summary>
        internal static BigInteger ConsBigInteger(int BitLength, int Certainty, SecureRandom Rnd)
        {
            // PRE: bitLength >= 2;
            // For small numbers get a random prime from the prime table
            if (BitLength <= 10)
            {
                int[] rp = _offsetPrimes[BitLength];
                return(_biPrimes[rp[0] + Rnd.NextInt32(rp[1])]);
            }
            int        shiftCount = (-BitLength) & 31;
            int        last       = (BitLength + 31) >> 5;
            BigInteger n          = new BigInteger(1, last, new int[last]);

            last--;
            do
            {// To fill the array with random integers
                for (int i = 0; i < n._numberLength; i++)
                {
                    n._digits[i] = Rnd.Next();
                }

                // To fix to the correct bitLength
                // n.digits[last] |= 0x80000000;
                n._digits[last] |= Int32.MinValue;
                n._digits[last]  = IntUtils.URShift(n._digits[last], shiftCount);
                // To create an odd number
                n._digits[0] |= 1;
            } while (!IsProbablePrime(n, Certainty));

            return(n);
        }
Пример #7
0
        private static BigInteger MultiplyPAP(BigInteger X, BigInteger Y)
        {
            // Multiplies two BigIntegers. Implements traditional scholar algorithm described by Knuth.
            // PRE: a >= b
            int aLen      = X._numberLength;
            int bLen      = Y._numberLength;
            int resLength = aLen + bLen;
            int resSign   = (X._sign != Y._sign) ? -1 : 1;

            // A special case when both numbers don't exceed int
            if (resLength == 2)
            {
                long val     = UnsignedMultAddAdd(X._digits[0], Y._digits[0], 0, 0);
                int  valueLo = (int)val;
                int  valueHi = (int)IntUtils.URShift(val, 32);

                return((valueHi == 0) ?
                       new BigInteger(resSign, valueLo) :
                       new BigInteger(resSign, 2, new int[] { valueLo, valueHi }));
            }
            int[] aDigits   = X._digits;
            int[] bDigits   = Y._digits;
            int[] resDigits = new int[resLength];
            // Common case
            MultiplyArraysPAP(aDigits, aLen, bDigits, bLen, resDigits);
            BigInteger result = new BigInteger(resSign, resLength, resDigits);

            result.CutOffLeadingZeroes();

            return(result);
        }
Пример #8
0
        /// <summary>
        /// Multiplies a number by a positive integer.
        /// </summary>
        ///
        /// <param name="X">An arbitrary BigInteger</param>
        /// <param name="Factor">A positive int number</param>
        ///
        /// <returns>X * Factor</returns>
        internal static BigInteger MultiplyByPositiveInt(BigInteger X, int Factor)
        {
            int resSign = X._sign;

            if (resSign == 0)
            {
                return(BigInteger.Zero);
            }

            int aNumberLength = X._numberLength;

            int[] aDigits = X._digits;

            if (aNumberLength == 1)
            {
                long res   = UnsignedMultAddAdd(aDigits[0], Factor, 0, 0);
                int  resLo = (int)res;
                int  resHi = (int)IntUtils.URShift(res, 32);

                return((resHi == 0) ?
                       new BigInteger(resSign, resLo) :
                       new BigInteger(resSign, 2, new int[] { resLo, resHi }));
            }
            // Common case
            int resLength = aNumberLength + 1;

            int[] resDigits = new int[resLength];

            resDigits[aNumberLength] = MultiplyByInt(resDigits, aDigits, aNumberLength, Factor);
            BigInteger result = new BigInteger(resSign, resLength, resDigits);

            result.CutOffLeadingZeroes();

            return(result);
        }
Пример #9
0
        /// <summary>
        /// Divides an array by an integer value. Implements the Knuth's division algorithm.
        /// <para>See D. Knuth, The Art of Computer Programming, vol. 2.</para>
        /// </summary>
        ///
        /// <param name="Destination">The quotient</param>
        /// <param name="Source">The dividend</param>
        /// <param name="SourceLength">The length of the dividend</param>
        /// <param name="Divisor">The divisor</param>
        ///
        /// <returns>Returns the remainder</returns>
        internal static int DivideArrayByInt(int[] Destination, int[] Source, int SourceLength, int Divisor)
        {
            long rem   = 0;
            long bLong = Divisor & 0xffffffffL;

            for (int i = SourceLength - 1; i >= 0; i--)
            {
                long temp = (rem << 32) | (Source[i] & 0xffffffffL);
                long quot;
                if (temp >= 0)
                {
                    quot = (temp / bLong);
                    rem  = (temp % bLong);
                }
                else
                {
                    // make the dividend positive shifting it right by 1 bit then
                    // get the quotient an remainder and correct them properly
                    long aPos = IntUtils.URShift(temp, 1);
                    long bPos = IntUtils.URShift(Divisor, 1);
                    quot = aPos / bPos;
                    rem  = aPos % bPos;
                    // double the remainder and add 1 if a is odd
                    rem = (rem << 1) + (temp & 1);
                    if ((Divisor & 1) != 0)
                    {
                        // the divisor is odd
                        if (quot <= rem)
                        {
                            rem -= quot;
                        }
                        else
                        {
                            if (quot - rem <= bLong)
                            {
                                rem  += bLong - quot;
                                quot -= 1;
                            }
                            else
                            {
                                rem  += (bLong << 1) - quot;
                                quot -= 2;
                            }
                        }
                    }
                }
                Destination[i] = (int)(quot & 0xffffffffL);
            }

            return((int)rem);
        }
Пример #10
0
        private static int MultiplyByInt(int[] Result, int[] X, int Size, int Factor)
        {
            // Multiplies an array of integers by an integer value and saves the result in Res
            long carry = 0;

            for (int i = 0; i < Size; i++)
            {
                carry     = UnsignedMultAddAdd(X[i], Factor, (int)carry, 0);
                Result[i] = (int)carry;
                carry     = IntUtils.URShift(carry, 32);
            }

            return((int)carry);
        }
Пример #11
0
        private static long DivideLongByInt(long X, int Y)
        {
            // divides an unsigned long X by an unsigned int Y
            //
            long quot;
            long rem;
            long bLong = Y & 0xffffffffL;

            if (X >= 0)
            {
                quot = (X / bLong);
                rem  = (X % bLong);
            }
            else
            {
                /*
                 * Make the dividend positive shifting it right by 1 bit then get
                 * the quotient an remainder and correct them properly
                 */
                long aPos = IntUtils.URShift(X, 1);
                long bPos = IntUtils.URShift(Y, 1);
                quot = aPos / bPos;
                rem  = aPos % bPos;
                // double the remainder and add 1 if a is odd
                rem = (rem << 1) + (X & 1);

                if ((Y & 1) != 0)
                { // the divisor is odd
                    if (quot <= rem)
                    {
                        rem -= quot;
                    }
                    else
                    {
                        if (quot - rem <= bLong)
                        {
                            rem  += bLong - quot;
                            quot -= 1;
                        }
                        else
                        {
                            rem  += (bLong << 1) - quot;
                            quot -= 2;
                        }
                    }
                }
            }
            return((rem << 32) | (quot & 0xffffffffL));
        }
Пример #12
0
        /// <summary>
        /// Performs <c>X = X Mod (2<sup>N</sup>)</c>
        /// </summary>
        /// <param name="X">A positive number, it will store the result</param>
        /// <param name="N">A positive exponent of 2</param>
        internal static void InplaceModPow2(BigInteger X, int N)
        {
            // PRE: (x > 0) and (n >= 0)
            int fd = N >> 5;
            int leadingZeros;

            if ((X._numberLength < fd) || (X.BitLength <= N))
            {
                return;
            }
            leadingZeros    = 32 - (N & 31);
            X._numberLength = fd + 1;
            X._digits[fd]  &= (leadingZeros < 32) ? (IntUtils.URShift(-1, leadingZeros)) : 0;
            X.CutOffLeadingZeroes();
        }
Пример #13
0
        /// <summary>
        /// Shifts the source digits left one bit, creating a value whose magnitude is doubled.
        /// </summary>
        ///
        /// <param name="Result">The result</param>
        /// <param name="Value">The source BigIntger</param>
        /// <param name="ValueLen">The value length</param>
        internal static void ShiftLeftOneBit(int[] Result, int[] Value, int ValueLen)
        {
            int carry = 0;

            for (int i = 0; i < ValueLen; i++)
            {
                int val = Value[i];
                Result[i] = (val << 1) | carry;
                carry     = IntUtils.URShift(val, 31);
            }
            if (carry != 0)
            {
                Result[ValueLen] = carry;
            }
        }
Пример #14
0
        /// <summary>
        /// Multiplies an array by int and subtracts it from a subarray of another array
        /// </summary>
        ///
        /// <param name="X">The array to subtract from</param>
        /// <param name="Start">The start element of the subarray of X</param>
        /// <param name="Y">The array to be multiplied and subtracted</param>
        /// <param name="YLength">The length of Y</param>
        /// <param name="Multiplier">The multiplier of Y</param>
        ///
        /// <returns>Returns the carry element of subtraction</returns>
        internal static int MultiplyAndSubtract(int[] X, int Start, int[] Y, int YLength, int Multiplier)
        {
            long carry0 = 0;
            long carry1 = 0;

            for (int i = 0; i < YLength; i++)
            {
                carry0       = Multiplication.UnsignedMultAddAdd(Y[i], Multiplier, (int)carry0, 0);
                carry1       = (X[Start + i] & 0xffffffffL) - (carry0 & 0xffffffffL) + carry1;
                X[Start + i] = (int)carry1;
                carry1     >>= 32; // -1 or 0
                carry0       = IntUtils.URShift(carry0, 32);
            }

            carry1             = (X[Start + YLength] & 0xffffffffL) - carry0 + carry1;
            X[Start + YLength] = (int)carry1;

            return((int)(carry1 >> 32)); // -1 or 0
        }
Пример #15
0
        private static void MultPAP(int[] X, int[] Y, int[] T, int ALen, int BLen)
        {
            if (X == Y && ALen == BLen)
            {
                Square(X, ALen, T);
                return;
            }

            for (int i = 0; i < ALen; i++)
            {
                long carry = 0;
                int  aI    = X[i];

                for (int j = 0; j < BLen; j++)
                {
                    carry    = UnsignedMultAddAdd(aI, Y[j], T[i + j], (int)carry);
                    T[i + j] = (int)carry;
                    carry    = IntUtils.URShift(carry, 32);
                }
                T[i + BLen] = (int)carry;
            }
        }
Пример #16
0
        /// <summary>
        /// Abstractly shifts left an array of integers in little endian (i.e. shift it right).
        /// Total shift distance in bits is intCount * 32 + count
        /// </summary>
        ///
        /// <param name="Result">The result</param>
        /// <param name="Value">The source BigIntger</param>
        /// <param name="IntCount">The number integers</param>
        /// <param name="N">The number of bits to shift</param>
        internal static void ShiftLeft(int[] Result, int[] Value, int IntCount, int N)
        {
            if (N == 0)
            {
                Array.Copy(Value, 0, Result, IntCount, Result.Length - IntCount);
            }
            else
            {
                int rightShiftCount = 32 - N;

                Result[Result.Length - 1] = 0;
                for (int i = Result.Length - 1; i > IntCount; i--)
                {
                    Result[i]    |= IntUtils.URShift(Value[i - IntCount - 1], rightShiftCount);
                    Result[i - 1] = Value[i - IntCount - 1] << N;
                }
            }

            for (int i = 0; i < IntCount; i++)
            {
                Result[i] = 0;
            }
        }
Пример #17
0
        /// <summary>
        /// See BigInteger#add(BigInteger)
        /// </summary>
        internal static BigInteger Add(BigInteger A, BigInteger B)
        {
            int[] resDigits;
            int   resSign;
            int   op1Sign = A._sign;
            int   op2Sign = B._sign;

            if (op1Sign == 0)
            {
                return(B);
            }
            if (op2Sign == 0)
            {
                return(A);
            }

            int op1Len = A._numberLength;
            int op2Len = B._numberLength;

            if (op1Len + op2Len == 2)
            {
                long a = (A._digits[0] & 0xFFFFFFFFL);
                long b = (B._digits[0] & 0xFFFFFFFFL);
                long res;
                int  valueLo;
                int  valueHi;

                if (op1Sign == op2Sign)
                {
                    res     = a + b;
                    valueLo = (int)res;
                    valueHi = (int)IntUtils.URShift(res, 32);

                    return((valueHi == 0)
                                ? new BigInteger(op1Sign, valueLo)
                                : new BigInteger(op1Sign, 2, new int[] { valueLo, valueHi }));
                }

                return(BigInteger.ValueOf((op1Sign < 0) ? (b - a) : (a - b)));
            }
            else if (op1Sign == op2Sign)
            {
                resSign = op1Sign;
                // an augend should not be shorter than addend
                resDigits = (op1Len >= op2Len) ?
                            Add(A._digits, op1Len, B._digits, op2Len) :
                            Add(B._digits, op2Len, A._digits, op1Len);
            }
            else
            {
                // signs are different
                int cmp = ((op1Len != op2Len) ?
                           ((op1Len > op2Len) ? 1 : -1) :
                           CompareArrays(A._digits, B._digits, op1Len));

                if (cmp == BigInteger.EQUALS)
                {
                    return(BigInteger.Zero);
                }

                // a minuend should not be shorter than subtrahend
                if (cmp == BigInteger.GREATER)
                {
                    resSign   = op1Sign;
                    resDigits = Subtract(A._digits, op1Len, B._digits, op2Len);
                }
                else
                {
                    resSign   = op2Sign;
                    resDigits = Subtract(B._digits, op2Len, A._digits, op1Len);
                }
            }
            BigInteger result = new BigInteger(resSign, resDigits.Length, resDigits);

            result.CutOffLeadingZeroes();

            return(result);
        }
Пример #18
0
        /// <summary>
        /// Divides the array 'a' by the array 'b' and gets the quotient and the remainder.
        /// <para>Implements the Knuth's division algorithm. See D. Knuth, The Art of Computer Programming,
        /// vol. 2. Steps D1-D8 correspond the steps in the algorithm description.</para>
        /// </summary>
        ///
        /// <param name="Quotient">The quotient</param>
        /// <param name="QuotientLen">The quotient's length</param>
        /// <param name="X">The dividend</param>
        /// <param name="XLen">The dividend's length</param>
        /// <param name="Y">The divisor</param>
        /// <param name="YLength">The divisor's length</param>
        ///
        /// <returns>eturn the remainder</returns>
        internal static int[] Divide(int[] Quotient, int QuotientLen, int[] X, int XLen, int[] Y, int YLength)
        {
            int[] normA = new int[XLen + 1];          // the normalized dividend
            // an extra byte is needed for correct shift
            int[] normB       = new int[YLength + 1]; // the normalized divisor;
            int   normBLength = YLength;

            // Step D1: normalize a and b and put the results to a1 and b1 the
            // normalized divisor's first digit must be >= 2^31
            int divisorShift = IntUtils.NumberOfLeadingZeros(Y[YLength - 1]);

            if (divisorShift != 0)
            {
                BitLevel.ShiftLeft(normB, Y, 0, divisorShift);
                BitLevel.ShiftLeft(normA, X, 0, divisorShift);
            }
            else
            {
                Array.Copy(X, 0, normA, 0, XLen);
                Array.Copy(Y, 0, normB, 0, YLength);
            }
            int firstDivisorDigit = normB[normBLength - 1];
            // Step D2: set the quotient index
            int i = QuotientLen - 1;
            int j = XLen;

            while (i >= 0)
            {
                // Step D3: calculate a guess digit guessDigit
                int guessDigit = 0;

                if (normA[j] == firstDivisorDigit)
                {
                    // set guessDigit to the largest unsigned int value
                    guessDigit = -1;
                }
                else
                {
                    long product = (((normA[j] & 0xffffffffL) << 32) + (normA[j - 1] & 0xffffffffL));
                    long res     = Division.DivideLongByInt(product, firstDivisorDigit);
                    guessDigit = (int)res;      // the quotient of divideLongByInt
                    int rem = (int)(res >> 32); // the remainder of
                    // divideLongByInt
                    // decrease guessDigit by 1 while leftHand > rightHand
                    if (guessDigit != 0)
                    {
                        long leftHand    = 0;
                        long rightHand   = 0;
                        bool rOverflowed = false;
                        guessDigit++; // to have the proper value in the loop
                        // below
                        do
                        {
                            guessDigit--;
                            if (rOverflowed)
                            {
                                break;
                            }

                            // leftHand always fits in an unsigned long
                            leftHand = (guessDigit & 0xffffffffL) * (normB[normBLength - 2] & 0xffffffffL);
                            // rightHand can overflow; in this case the loop
                            // condition will be true in the next step of the loop
                            rightHand = ((long)rem << 32) + (normA[j - 2] & 0xffffffffL);
                            long longR = (rem & 0xffffffffL) + (firstDivisorDigit & 0xffffffffL);
                            // checks that longR does not fit in an unsigned int;
                            // this ensures that rightHand will overflow unsigned long in the next step
                            if (IntUtils.NumberOfLeadingZeros((int)IntUtils.URShift(longR, 32)) < 32)
                            {
                                rOverflowed = true;
                            }
                            else
                            {
                                rem = (int)longR;
                            }
                        } while ((leftHand ^ Int64.MinValue) > (rightHand ^ Int64.MinValue));
                    }
                }
                // Step D4: multiply normB by guessDigit and subtract the production from normA.
                if (guessDigit != 0)
                {
                    int borrow = Division.MultiplyAndSubtract(normA, j - normBLength, normB, normBLength, guessDigit);
                    // Step D5: check the borrow
                    if (borrow != 0)
                    {
                        // Step D6: compensating addition
                        guessDigit--;
                        long carry = 0;
                        for (int k = 0; k < normBLength; k++)
                        {
                            carry += (normA[j - normBLength + k] & 0xffffffffL) + (normB[k] & 0xffffffffL);
                            normA[j - normBLength + k] = (int)carry;
                            carry = IntUtils.URShift(carry, 32);
                        }
                    }
                }
                if (Quotient != null)
                {
                    Quotient[i] = guessDigit;
                }
                // Step D7
                j--;
                i--;
            }
            // Step D8: we got the remainder in normA. Denormalize it as needed
            if (divisorShift != 0)
            {
                // reuse normB
                BitLevel.ShiftRight(normB, normBLength, normA, 0, divisorShift);
                return(normB);
            }
            Array.Copy(normA, 0, normB, 0, YLength);

            return(normA);
        }