Recycle() public method

public Recycle ( ) : void
return void
示例#1
0
        public void DivideSingleByte(BigInteger bi2)
        {
            int resultPos = 0;

            ulong divisor  = (ulong)bi2.Data[0];
            int   pos      = Length - 1;
            ulong dividend = (ulong)Data[pos];

            var remainder = new BigInteger(this);

            if (dividend >= divisor)
            {
                ulong quotient = dividend / divisor;
                Data[resultPos++]   = (uint)quotient;
                remainder.Data[pos] = (uint)(dividend % divisor);
            }
            pos--;
            while (pos >= 0)
            {
                //Console.WriteLine(pos);
                dividend = ((ulong)remainder.Data[pos + 1] << 32) + (ulong)remainder.Data[pos];
                ulong quotient = dividend / divisor;
                Data[resultPos++]       = (uint)quotient;
                remainder.Data[pos + 1] = 0;
                remainder.Data[pos--]   = (uint)(dividend % divisor);
                //Console.WriteLine(">>>> " + bi1);
            }
            Length = resultPos;
            remainder.Recycle();
        }
示例#2
0
        public void DivideMultiByte(BigInteger bi2)
        {
            int remainderLen = Length + 1;

            uint mask = 0x80000000;
            uint val = bi2.Data[bi2.Length - 1];
            int  shift = 0, resultPos = 0;

            while (mask != 0 && (val & mask) == 0)
            {
                shift++; mask >>= 1;
            }
            var remainder = new BigInteger(this)
            {
                Length = remainderLen
            };

            shiftLeft(remainder.Data, shift);
            bi2 = bi2 << shift;

            int j   = remainderLen - bi2.Length;
            int pos = remainderLen - 1;

            ulong firstDivisorByte  = bi2.Data[bi2.Length - 1];
            ulong secondDivisorByte = bi2.Data[bi2.Length - 2];

            int divisorLen = bi2.Length + 1;
            var kk         = new BigInteger(0)
            {
                Length = divisorLen
            };
            var ss = new BigInteger(0);

            while (j > 0)
            {
                ulong dividend = ((ulong)remainder.Data[pos] << 32) + (ulong)remainder.Data[pos - 1];

                ulong q_hat = dividend / firstDivisorByte;
                ulong r_hat = dividend % firstDivisorByte;
                bool  done  = false;
                while (!done)
                {
                    done = true;

                    if (q_hat == 0x100000000 ||
                        (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder.Data[pos - 2]))
                    {
                        q_hat--;
                        r_hat += firstDivisorByte;

                        if (r_hat < 0x100000000)
                        {
                            done = false;
                        }
                    }
                }
                kk.Length = divisorLen;
                Array.Copy(remainder.Data, pos - divisorLen + 1, kk.Data, 0, divisorLen);
                while (kk.Length > 1 && kk.Data[kk.Length - 1] == 0)
                {
                    kk.Length--;
                }

                // BigInteger ss = bi2 * (long)q_hat;
                Multiply(bi2, q_hat, ref ss);
                while (ss > kk)
                {
                    q_hat--;
                    ss.Subtract(bi2);
                }
                kk.Subtract(ss);

                Array.Copy(kk.Data, 0, remainder.Data, pos - divisorLen + 1, divisorLen);

                Data[resultPos++] = (uint)q_hat;
                pos--;
                j--;
            }
            Length = resultPos;
            Array.Reverse(Data, 0, Length);
            Array.Clear(Data, Length, maxLength - Length);
            while (Length > 1 && Data[Length - 1] == 0)
            {
                Length--;
            }
            if (Length == 0)
            {
                Length = 1;
            }
            kk.Recycle();
            ss.Recycle();
            remainder.Recycle();
        }
示例#3
0
        //***********************************************************************
        // Fast calculation of modular reduction using Barrett's reduction.
        // Requires x < b^(2k), where b is the base.  In this case, base is
        // 2^32 (uint).
        //
        // Reference [4]
        //***********************************************************************

        private void BarrettReduction(ref BigInteger x1, BigInteger x2, BigInteger n, BigInteger constant, ref BigInteger temp)
        {
            Multiply(x1, x2, ref temp);
            int k         = n.Length,
                kPlusOne  = k + 1,
                kMinusOne = k - 1;

            //var q1 = new BigInteger(0);

            //// q1 = x / b^(k-1)

            //for (int i = kMinusOne, j = 0; i < x.Length; i++, j++)
            //    q1.Data[j] = x.Data[i];
            //q1.Length = x.Length - kMinusOne;
            //if(q1.Length <= 0)
            //    q1.Length = 1;

            //var q2 = q1 * constant;
            //q1.Recycle();
            //q1 = q2;

            var q1 = new BigIntegerShell(temp, kMinusOne, temp.Length - kMinusOne) * constant;

            // r1 = x mod b^(k+1)
            // i.e. keep the lowest (k+1) words
            //var r1 = new BigInteger(0);
            //int lengthToCopy = (x.Length > kPlusOne) ? kPlusOne : x.Length;
            temp.Length = (temp.Length > kPlusOne) ? kPlusOne : temp.Length;
            //for(int i = 0; i < lengthToCopy; i++)
            //    r1.Data[i] = x.Data[i];
            //r1.Length = lengthToCopy;

            // r2 = (q3 * n) mod b^(k+1)
            // partial multiplication of q3 and n

            var r2 = new BigInteger(0);

            for (int i = kPlusOne; i < q1.Length; i++)
            {
                if (q1.Data[i] == 0)
                {
                    continue;
                }

                ulong mcarry = 0;
                int   t      = i - kPlusOne;
                for (int j = 0; j < n.Length && t < kPlusOne; j++, t++)
                {
                    // t = i + j
                    ulong val = (q1.Data[i] * (ulong)n.Data[j]) +
                                r2.Data[t] + mcarry;

                    r2.Data[t] = (uint)val;
                    mcarry     = (val >> 32);
                }

                if (t < kPlusOne)
                {
                    r2.Data[t] = (uint)mcarry;
                }
            }
            r2.Length = kPlusOne;
            while (r2.Length > 1 && r2.Data[r2.Length - 1] == 0)
            {
                r2.Length--;
            }

            temp.Subtract(r2);
            r2.Recycle();
            if ((temp.Data[maxLength - 1] & 0x80000000) != 0)        // negative
            {
                ulong carry = 1;
                for (var i = kPlusOne; carry != 0 && i < maxLength; i++)
                {
                    var sum = temp.Data[i] + carry;
                    carry        = sum >> 32;
                    temp.Data[i] = (uint)sum;
                }
            }

            while (temp >= n)
            {
                temp.Subtract(n);
            }
            q1.Recycle();
            q1   = temp;
            temp = x1;
            x1   = q1;
        }
示例#4
0
        //***********************************************************************
        // Modulo Exponentiation
        //***********************************************************************

        public BigInteger ModPow(BigInteger exp, BigInteger n)
        {
            if ((exp.Data[maxLength - 1] & 0x80000000) != 0)
            {
                throw (new ArithmeticException("Positive exponents only."));
            }

            BigInteger resultNum = 1;
            BigInteger tempNum;
            bool       thisNegative = false;

            if ((this.Data[maxLength - 1] & 0x80000000) != 0)   // negative this
            {
                tempNum      = -this % n;
                thisNegative = true;
            }
            else
            {
                tempNum = this % n;                        // ensures (tempNum * tempNum) < b^(2k)
            }
            if ((n.Data[maxLength - 1] & 0x80000000) != 0) // negative n
            {
                n = -n;
            }

            // calculate constant = b^(2k) / m
            var constant = new BigInteger(0);

            int i = n.Length << 1;

            constant.Data[i] = 0x00000001;
            constant.Length  = i + 1;
            constant.Divide(n);
            //constant /= n;
            int totalBits = exp.bitCount();
            int count     = 0;
            var temp      = new BigInteger(0);

            // perform squaring and multiply exponentiation
            for (var pos = 0; pos < exp.Length; pos++)
            {
                uint mask = 0x01;
                //Console.WriteLine("pos = " + pos);

                for (var index = 0; index < 32; index++)
                {
                    if ((exp.Data[pos] & mask) != 0)
                    {
                        BarrettReduction(ref resultNum, tempNum, n, constant, ref temp);
                    }
                    mask <<= 1;
                    BarrettReduction(ref tempNum, tempNum, n, constant, ref temp);

                    if (tempNum.Length == 1 && tempNum.Data[0] == 1)
                    {
                        if (thisNegative && (exp.Data[0] & 0x1) != 0)    //odd exp
                        {
                            resultNum.Negative();
                        }
                        return(resultNum);
                    }
                    count++;
                    if (count == totalBits)
                    {
                        break;
                    }
                }
            }
            constant.Recycle();
            temp.Recycle();
            if (thisNegative && (exp.Data[0] & 0x1) != 0)    //odd exp
            {
                resultNum.Negative();
            }

            return(resultNum);
        }
示例#5
0
        public BigInteger GetRemainderMultiByte(BigInteger bi2)
        {
            var remainder = new BigInteger(this);

            remainder.Length++;
            uint mask  = 0x80000000;
            uint val   = bi2.Data[bi2.Length - 1];
            int  shift = 0;

            while (mask != 0 && (val & mask) == 0)
            {
                shift++; mask >>= 1;
            }

            shiftLeft(remainder.Data, shift);
            bi2 = bi2 << shift;

            int j   = remainder.Length - bi2.Length;
            int pos = remainder.Length - 1;

            ulong firstDivisorByte  = bi2.Data[bi2.Length - 1];
            ulong secondDivisorByte = bi2.Data[bi2.Length - 2];

            int divisorLen = bi2.Length + 1;

            var kk = new BigInteger(0)
            {
                Length = divisorLen
            };
            var ss = new BigInteger(0);

            while (j > 0)
            {
                ulong dividend = ((ulong)remainder.Data[pos] << 32) + (ulong)remainder.Data[pos - 1];
                //Console.WriteLine("dividend = {0}", dividend);

                ulong q_hat = dividend / firstDivisorByte;
                ulong r_hat = dividend % firstDivisorByte;

                //Console.WriteLine("q_hat = {0:X}, r_hat = {1:X}", q_hat, r_hat);

                bool done = false;
                while (!done)
                {
                    done = true;

                    if (q_hat == 0x100000000 ||
                        (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder.Data[pos - 2]))
                    {
                        q_hat--;
                        r_hat += firstDivisorByte;

                        if (r_hat < 0x100000000)
                        {
                            done = false;
                        }
                    }
                }

                kk.Length = divisorLen;
                Array.Copy(remainder.Data, pos - divisorLen + 1, kk.Data, 0, divisorLen);
                while (kk.Length > 1 && kk.Data[kk.Length - 1] == 0)
                {
                    kk.Length--;
                }
                //var ss = bi2 * (long)q_hat;
                Multiply(bi2, q_hat, ref ss);
                while (ss > kk)
                {
                    q_hat--;
                    ss.Subtract(bi2);
                }
                kk.Subtract(ss);
                Array.Copy(kk.Data, 0, remainder.Data, pos - divisorLen + 1, divisorLen);
                pos--;
                j--;
            }
            ss.Recycle();
            kk.Recycle();
            remainder.Length = shiftRight(remainder.Data, shift);
            return(remainder);
        }
示例#6
0
        public void DivideSingleByte(BigInteger bi2)
        {
            int resultPos = 0;

            ulong divisor = (ulong)bi2.Data[0];
            int pos = Length - 1;
            ulong dividend = (ulong)Data[pos];

            var remainder = new BigInteger(this);
         
            if (dividend >= divisor)
            {
                ulong quotient = dividend / divisor;
                Data[resultPos++] = (uint)quotient;
                remainder.Data[pos] = (uint)(dividend % divisor);
            }
            pos--;
            while (pos >= 0)
            {
                //Console.WriteLine(pos);
                dividend = ((ulong)remainder.Data[pos + 1] << 32) + (ulong)remainder.Data[pos];
                ulong quotient = dividend / divisor;
                Data[resultPos++] = (uint)quotient;
                remainder.Data[pos + 1] = 0;
                remainder.Data[pos--] = (uint)(dividend % divisor);
                //Console.WriteLine(">>>> " + bi1);
            }
            Length = resultPos;
            remainder.Recycle();
        }
示例#7
0
        public BigInteger GetRemainderMultiByte(BigInteger bi2)
        {
            var remainder = new BigInteger(this);
            remainder.Length++;
            uint mask = 0x80000000;
            uint val = bi2.Data[bi2.Length - 1];
            int shift = 0;

            while (mask != 0 && (val & mask) == 0)
            {
                shift++; mask >>= 1;
            }

            shiftLeft(remainder.Data, shift);
            bi2 = bi2 << shift;

            int j = remainder.Length - bi2.Length;
            int pos = remainder.Length - 1;

            ulong firstDivisorByte = bi2.Data[bi2.Length - 1];
            ulong secondDivisorByte = bi2.Data[bi2.Length - 2];

            int divisorLen = bi2.Length + 1;
          
            var kk = new BigInteger(0) { Length = divisorLen };
            var ss = new BigInteger(0);
            while (j > 0)
            {
                ulong dividend = ((ulong)remainder.Data[pos] << 32) + (ulong)remainder.Data[pos - 1];
                //Console.WriteLine("dividend = {0}", dividend);

                ulong q_hat = dividend / firstDivisorByte;
                ulong r_hat = dividend % firstDivisorByte;

                //Console.WriteLine("q_hat = {0:X}, r_hat = {1:X}", q_hat, r_hat);

                bool done = false;
                while (!done)
                {
                    done = true;

                    if (q_hat == 0x100000000 ||
                       (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder.Data[pos - 2]))
                    {
                        q_hat--;
                        r_hat += firstDivisorByte;

                        if (r_hat < 0x100000000)
                            done = false;
                    }
                }

                kk.Length = divisorLen;
                Array.Copy(remainder.Data, pos - divisorLen + 1, kk.Data, 0, divisorLen);
                while (kk.Length > 1 && kk.Data[kk.Length - 1] == 0)kk.Length--;
                //var ss = bi2 * (long)q_hat;
                Multiply(bi2, q_hat, ref ss);
                while (ss > kk)
                {
                    q_hat--;
                    ss.Subtract(bi2);
                }
                kk.Subtract(ss);
                Array.Copy(kk.Data, 0, remainder.Data, pos - divisorLen + 1, divisorLen);
                pos--;
                j--;
            }
            ss.Recycle();
            kk.Recycle();
            remainder.Length = shiftRight(remainder.Data, shift);
            return remainder;
        }
示例#8
0
        public void DivideMultiByte(BigInteger bi2)
        {
            int remainderLen = Length + 1;

            uint mask = 0x80000000;
            uint val = bi2.Data[bi2.Length - 1];
            int shift = 0, resultPos = 0;

            while (mask != 0 && (val & mask) == 0)
            {
                shift++; mask >>= 1;
            }
            var remainder = new BigInteger(this) {Length = remainderLen};
            shiftLeft(remainder.Data, shift);
            bi2 = bi2 << shift;

            int j = remainderLen - bi2.Length;
            int pos = remainderLen - 1;

            ulong firstDivisorByte = bi2.Data[bi2.Length - 1];
            ulong secondDivisorByte = bi2.Data[bi2.Length - 2];

            int divisorLen = bi2.Length + 1;
            var kk = new BigInteger(0) {Length = divisorLen};
            var ss = new BigInteger(0);
            while (j > 0)
            {
                ulong dividend = ((ulong)remainder.Data[pos] << 32) + (ulong)remainder.Data[pos - 1];

                ulong q_hat = dividend / firstDivisorByte;
                ulong r_hat = dividend % firstDivisorByte;
                bool done = false;
                while (!done)
                {
                    done = true;

                    if (q_hat == 0x100000000 ||
                       (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder.Data[pos - 2]))
                    {
                        q_hat--;
                        r_hat += firstDivisorByte;

                        if (r_hat < 0x100000000)
                            done = false;
                    }
                }
                kk.Length = divisorLen;
                Array.Copy(remainder.Data, pos - divisorLen + 1 ,kk.Data, 0, divisorLen);
                while (kk.Length > 1 && kk.Data[kk.Length - 1] == 0)
                    kk.Length--;
                
               // BigInteger ss = bi2 * (long)q_hat;
                Multiply(bi2,q_hat,ref ss);
                while (ss > kk)
                {
                    q_hat--;
                    ss.Subtract(bi2);
                }
                kk.Subtract(ss);
                
                Array.Copy(kk.Data,0, remainder.Data, pos - divisorLen + 1, divisorLen);
 
                Data[resultPos++] = (uint)q_hat;
                pos--;
                j--;
            }
            Length = resultPos;
            Array.Reverse(Data,0,Length);
            Array.Clear(Data,Length,maxLength-Length);
            while (Length > 1 && Data[Length - 1] == 0)
                Length--;
            if (Length == 0)
                Length = 1;
            kk.Recycle();
            ss.Recycle();
            remainder.Recycle();
        }
示例#9
0
        //***********************************************************************
        // Fast calculation of modular reduction using Barrett's reduction.
        // Requires x < b^(2k), where b is the base.  In this case, base is
        // 2^32 (uint).
        //
        // Reference [4]
        //***********************************************************************

        private void BarrettReduction(ref BigInteger x1,BigInteger x2, BigInteger n, BigInteger constant,ref BigInteger temp)
        {
            Multiply(x1, x2, ref temp);
            int k = n.Length,
                kPlusOne = k+1,
                kMinusOne = k-1;

            //var q1 = new BigInteger(0);

            //// q1 = x / b^(k-1)

            //for (int i = kMinusOne, j = 0; i < x.Length; i++, j++)
            //    q1.Data[j] = x.Data[i];
            //q1.Length = x.Length - kMinusOne;
            //if(q1.Length <= 0)
            //    q1.Length = 1;

            //var q2 = q1 * constant;
            //q1.Recycle();
            //q1 = q2;

            var q1 = new BigIntegerShell(temp, kMinusOne, temp.Length - kMinusOne) * constant;
            // r1 = x mod b^(k+1)
            // i.e. keep the lowest (k+1) words
            //var r1 = new BigInteger(0);
            //int lengthToCopy = (x.Length > kPlusOne) ? kPlusOne : x.Length;
            temp.Length = (temp.Length > kPlusOne) ? kPlusOne : temp.Length;
            //for(int i = 0; i < lengthToCopy; i++)
            //    r1.Data[i] = x.Data[i];
            //r1.Length = lengthToCopy;

            // r2 = (q3 * n) mod b^(k+1)
            // partial multiplication of q3 and n

            var r2 = new BigInteger(0);
            for (int i = kPlusOne; i < q1.Length; i++)
            {
                if(q1.Data[i] == 0)     continue;

                ulong mcarry = 0;
                int t = i - kPlusOne;
                for(int j = 0; j < n.Length && t < kPlusOne; j++, t++)
                {
                    // t = i + j
                    ulong val = (q1.Data[i] * (ulong)n.Data[j]) +
                                r2.Data[t] + mcarry;

                    r2.Data[t] = (uint)val;
                    mcarry = (val >> 32);
                }

                if(t < kPlusOne)
                    r2.Data[t] = (uint)mcarry;
            }
            r2.Length = kPlusOne;
            while(r2.Length > 1 && r2.Data[r2.Length-1] == 0)
                r2.Length--;

            temp.Subtract(r2);
            r2.Recycle();
            if ((temp.Data[maxLength - 1] & 0x80000000) != 0)        // negative
            {
                ulong carry = 1;
                for (var i = kPlusOne; carry != 0 && i<maxLength; i++)
                {
                    var sum = temp.Data[i] + carry;
                    carry = sum >> 32;
                    temp.Data[i] = (uint)sum;
                }
            }

            while (temp >= n)
                temp.Subtract(n);
            q1.Recycle();
            q1 = temp;
            temp = x1;
            x1 = q1;
        }
示例#10
0
        //***********************************************************************
        // Modulo Exponentiation
        //***********************************************************************

        public BigInteger ModPow(BigInteger exp, BigInteger n)
        {
            if((exp.Data[maxLength-1] & 0x80000000) != 0)
                throw (new ArithmeticException("Positive exponents only."));

            BigInteger resultNum = 1;
            BigInteger tempNum;
            bool thisNegative = false;

            if((this.Data[maxLength-1] & 0x80000000) != 0)   // negative this
            {
                tempNum = -this % n;
                thisNegative = true;
            }
            else
                tempNum = this % n;  // ensures (tempNum * tempNum) < b^(2k)

            if((n.Data[maxLength-1] & 0x80000000) != 0)   // negative n
                n = -n;

            // calculate constant = b^(2k) / m
            var constant = new BigInteger(0);

            int i = n.Length << 1;
            constant.Data[i] = 0x00000001;
            constant.Length = i + 1;
            constant.Divide(n);
            //constant /= n;
            int totalBits = exp.bitCount();
            int count = 0;
            var temp = new BigInteger(0);
            // perform squaring and multiply exponentiation
            for(var pos = 0; pos < exp.Length; pos++)
            {
                uint mask = 0x01;
                //Console.WriteLine("pos = " + pos);

                for(var index = 0; index < 32; index++)
                {
                   
                    if ((exp.Data[pos] & mask) != 0)
                    {
                        BarrettReduction(ref resultNum, tempNum, n, constant, ref temp);
                    }
                    mask <<= 1;
                    BarrettReduction(ref tempNum, tempNum, n, constant, ref temp);

                    if(tempNum.Length == 1 && tempNum.Data[0] == 1)
                    {
                        if(thisNegative && (exp.Data[0] & 0x1) != 0)    //odd exp
                            resultNum.Negative();
                        return resultNum;
                    }
                    count++;
                    if(count == totalBits)
                        break;
                }
            }
            constant.Recycle();
            temp.Recycle();
            if(thisNegative && (exp.Data[0] & 0x1) != 0)    //odd exp
                resultNum.Negative();

            return resultNum;
        }