BigInteger.BarrettReduction C# (CSharp) Method

BarrettReduction() private method

private BarrettReduction ( BigInteger, x, BigInteger, n, BigInteger, constant ) : BigInteger,
x BigInteger,
n BigInteger,
constant BigInteger,
return BigInteger,
        private BigInteger BarrettReduction(BigInteger x, BigInteger n, BigInteger constant)
        {
                int k = n.dataLength,
                    kPlusOne = k+1,
                    kMinusOne = k-1;

                BigInteger q1 = new BigInteger();

                // q1 = x / b^(k-1)
                for(int i = kMinusOne, j = 0; i < x.dataLength; i++, j++)
                        q1.data[j] = x.data[i];
                q1.dataLength = x.dataLength - kMinusOne;
                if(q1.dataLength <= 0)
                        q1.dataLength = 1;


                BigInteger q2 = q1 * constant;
                BigInteger q3 = new BigInteger();

                // q3 = q2 / b^(k+1)
                for(int i = kPlusOne, j = 0; i < q2.dataLength; i++, j++)
                        q3.data[j] = q2.data[i];
                q3.dataLength = q2.dataLength - kPlusOne;
                if(q3.dataLength <= 0)
                        q3.dataLength = 1;


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


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

                BigInteger r2 = new BigInteger();
                for(int i = 0; i < q3.dataLength; i++)
                {
                        if(q3.data[i] == 0)     continue;

                        ulong mcarry = 0;
                        int t = i;
                        for(int j = 0; j < n.dataLength && t < kPlusOne; j++, t++)
                        {
                                // t = i + j
                                ulong val = ((ulong)q3.data[i] * (ulong)n.data[j]) +
                                             (ulong)r2.data[t] + mcarry;

                                r2.data[t] = (uint)(val & 0xFFFFFFFF);
                                mcarry = (val >> 32);
                        }

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

                r1 -= r2;
                if((r1.data[maxLength-1] & 0x80000000) != 0)        // negative
                {
                        BigInteger val = new BigInteger();
                        val.data[kPlusOne] = 0x00000001;
                        val.dataLength = kPlusOne + 1;
                        r1 += val;
                }

                while(r1 >= n)
                        r1 -= n;

                return r1;
        }

Usage Example

Ejemplo n.º 1
0
        //***********************************************************************
        // Performs the calculation of the kth term in the Lucas Sequence.
        // For details of the algorithm, see reference [9].
        //
        // k must be odd.  i.e LSB == 1
        //***********************************************************************

        private static BigInteger[] LucasSequenceHelper(BigInteger P, BigInteger Q,
                                                        BigInteger k, BigInteger n,
                                                        BigInteger constant, int s)
        {
                BigInteger[] result = new BigInteger[3];

                if((k.data[0] & 0x00000001) == 0)
                        throw (new ArgumentException("Argument k must be odd."));

                int numbits = k.bitCount();
                uint mask = (uint)0x1 << ((numbits & 0x1F) - 1);

                // v = v0, v1 = v1, u1 = u1, Q_k = Q^0

                BigInteger v = 2 % n, Q_k = 1 % n,
                           v1 = P % n, u1 = Q_k;
                bool flag = true;

                for(int i = k.dataLength - 1; i >= 0 ; i--)     // iterate on the binary expansion of k
                {
                        //Console.WriteLine("round");
                        while(mask != 0)
                        {
                                if(i == 0 && mask == 0x00000001)        // last bit
                                        break;

                                if((k.data[i] & mask) != 0)             // bit is set
                                {
                                        // index doubling with addition

                                        u1 = (u1 * v1) % n;

                                        v = ((v * v1) - (P * Q_k)) % n;
                                        v1 = n.BarrettReduction(v1 * v1, n, constant);
                                        v1 = (v1 - ((Q_k * Q) << 1)) % n;

                                        if(flag)
                                                flag = false;
                                        else
                                                Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);

                                        Q_k = (Q_k * Q) % n;
                                }
                                else
                                {
                                        // index doubling
                                        u1 = ((u1 * v) - Q_k) % n;

                                        v1 = ((v * v1) - (P * Q_k)) % n;
                                        v = n.BarrettReduction(v * v, n, constant);
                                        v = (v - (Q_k << 1)) % n;

                                        if(flag)
                                        {
                                                Q_k = Q % n;
                                                flag = false;
                                        }
                                        else
                                                Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);
                               }

                               mask >>= 1;
                        }
                        mask = 0x80000000;
                }

                // at this point u1 = u(n+1) and v = v(n)
                // since the last bit always 1, we need to transform u1 to u(2n+1) and v to v(2n+1)

                u1 = ((u1 * v) - Q_k) % n;
                v = ((v * v1) - (P * Q_k)) % n;
                if(flag)
                        flag = false;
                else
                        Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);

                Q_k = (Q_k * Q) % n;


                for(int i = 0; i < s; i++)
                {
                        // index doubling
                        u1 = (u1 * v) % n;
                        v = ((v * v) - (Q_k << 1)) % n;

                        if(flag)
                        {
                                Q_k = Q % n;
                                flag = false;
                        }
                        else
                                Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);
                }

                result[0] = u1;
                result[1] = v;
                result[2] = Q_k;

                return result;
        }
All Usage Examples Of BigInteger::BarrettReduction