예제 #1
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;
        }
예제 #2
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;
        }