Normalize() private method

Normalizes this by setting the length to the actual number of uints used in data and by setting the sign to Sign.Zero if the value of this is 0.
private Normalize ( ) : void
return void
Exemplo n.º 1
0
        public static BigInteger operator *(BigInteger bi1, BigInteger bi2)
        {
            if (bi1 == 0 || bi2 == 0)
            {
                return(0);
            }

            //
            // Validate pointers
            //
            if (bi1.data.Length < bi1.length)
            {
                throw new IndexOutOfRangeException("bi1 out of range");
            }
            if (bi2.data.Length < bi2.length)
            {
                throw new IndexOutOfRangeException("bi2 out of range");
            }

            var ret = new BigInteger(Sign.Positive, bi1.length + bi2.length);

            Kernel.Multiply(bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);

            ret.Normalize();
            return(ret);
        }
Exemplo n.º 2
0
            public static BigInteger RightShift(BigInteger bi, int n)
            {
                if (n == 0)
                {
                    return(new BigInteger(bi));
                }

                var w = n >> 5;
                var s = n & ((1 << 5) - 1);

                var ret = new BigInteger(Sign.Positive, bi.length - (uint)w + 1);
                var l   = (uint)ret.data.Length - 1;

                if (s != 0)
                {
                    uint x, carry = 0;

                    while (l-- > 0)
                    {
                        x           = bi.data[l + w];
                        ret.data[l] = (x >> n) | carry;
                        carry       = x << (32 - n);
                    }
                }
                else
                {
                    while (l-- > 0)
                    {
                        ret.data[l] = bi.data[l + w];
                    }
                }
                ret.Normalize();
                return(ret);
            }
Exemplo n.º 3
0
            public static BigInteger Subtract(BigInteger big, BigInteger small)
            {
                var result = new BigInteger(Sign.Positive, big.length);

                uint[] r = result.data, b = big.data, s = small.data;
                uint   i = 0, c = 0;

                do
                {
                    var x = s[i];
                    if (((x += c) < c) | ((r[i] = b[i] - x) > ~x))
                    {
                        c = 1;
                    }
                    else
                    {
                        c = 0;
                    }
                } while (++i < small.length);

                if (i == big.length)
                {
                    goto fixup;
                }

                if (c == 1)
                {
                    do
                    {
                        r[i] = b[i] - 1;
                    } while (b[i++] == 0 && i < big.length);

                    if (i == big.length)
                    {
                        goto fixup;
                    }
                }

                do
                {
                    r[i] = b[i];
                } while (++i < big.length);

fixup:

                result.Normalize();
                return(result);
            }
Exemplo n.º 4
0
            /// <summary>
            ///     Performs n / d and n % d in one operation.
            /// </summary>
            /// <param name="n">A BigInteger, upon exit this will hold n / d</param>
            /// <param name="d">The divisor</param>
            /// <returns>n % d</returns>
            public static uint SingleByteDivideInPlace(BigInteger n, uint d)
            {
                ulong r = 0;
                var   i = n.length;

                while (i-- > 0)
                {
                    r       <<= 32;
                    r        |= n.data[i];
                    n.data[i] = (uint)(r / d);
                    r        %= d;
                }
                n.Normalize();

                return((uint)r);
            }
Exemplo n.º 5
0
            public static BigInteger MultiplyByDword(BigInteger n, uint f)
            {
                var ret = new BigInteger(Sign.Positive, n.length + 1);

                uint  i = 0;
                ulong c = 0;

                do
                {
                    c          += n.data[i] * (ulong)f;
                    ret.data[i] = (uint)c;
                    c         >>= 32;
                } while (++i < n.length);
                ret.data[i] = (uint)c;
                ret.Normalize();
                return(ret);
            }
Exemplo n.º 6
0
            public static BigInteger DwordDiv(BigInteger n, uint d)
            {
                var ret = new BigInteger(Sign.Positive, n.length);

                ulong r = 0;
                var   i = n.length;

                while (i-- > 0)
                {
                    r         <<= 32;
                    r          |= n.data[i];
                    ret.data[i] = (uint)(r / d);
                    r          %= d;
                }
                ret.Normalize();

                return(ret);
            }
Exemplo n.º 7
0
            public static BigInteger LeftShift(BigInteger bi, int n)
            {
                if (n == 0)
                {
                    return(new BigInteger(bi, bi.length + 1));
                }

                var w = n >> 5;

                n &= ((1 << 5) - 1);

                var ret = new BigInteger(Sign.Positive, bi.length + 1 + (uint)w);

                uint i = 0, l = bi.length;

                if (n != 0)
                {
                    uint x, carry = 0;
                    while (i < l)
                    {
                        x = bi.data[i];
                        ret.data[i + w] = (x << n) | carry;
                        carry           = x >> (32 - n);
                        i++;
                    }
                    ret.data[i + w] = carry;
                }
                else
                {
                    while (i < l)
                    {
                        ret.data[i + w] = bi.data[i];
                        i++;
                    }
                }

                ret.Normalize();
                return(ret);
            }
Exemplo n.º 8
0
            public static BigInteger[] multiByteDivide(BigInteger bi1, BigInteger bi2)
            {
                if (Compare(bi1, bi2) == Sign.Negative)
                {
                    return new BigInteger[2] {
                               0, new BigInteger(bi1)
                    }
                }
                ;

                bi1.Normalize();
                bi2.Normalize();

                if (bi2.length == 1)
                {
                    return(DwordDivMod(bi1, bi2.data[0]));
                }

                var remainderLen = bi1.length + 1;
                var divisorLen   = (int)bi2.length + 1;

                var mask      = 0x80000000;
                var val       = bi2.data[bi2.length - 1];
                var shift     = 0;
                var resultPos = (int)bi1.length - (int)bi2.length;

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

                var quot = new BigInteger(Sign.Positive, bi1.length - bi2.length + 1);
                var rem  = (bi1 << shift);

                var remainder = rem.data;

                bi2 = bi2 << shift;

                var j   = (int)(remainderLen - bi2.length);
                var pos = (int)remainderLen - 1;

                var   firstDivisorByte  = bi2.data[bi2.length - 1];
                ulong secondDivisorByte = bi2.data[bi2.length - 2];

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

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

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

                            if (r_hat < 0x100000000)
                            {
                                continue;
                            }
                        }
                        break;
                    } while (true);

                    //
                    // At this point, q_hat is either exact, or one too large
                    // (more likely to be exact) so, we attempt to multiply the
                    // divisor by q_hat, if we get a borrow, we just subtract
                    // one from q_hat and add the divisor back.
                    //

                    uint  t;
                    uint  dPos       = 0;
                    var   nPos       = pos - divisorLen + 1;
                    ulong mc         = 0;
                    var   uint_q_hat = (uint)q_hat;
                    do
                    {
                        mc += bi2.data[dPos] * (ulong)uint_q_hat;
                        t   = remainder[nPos];
                        remainder[nPos] -= (uint)mc;
                        mc >>= 32;
                        if (remainder[nPos] > t)
                        {
                            mc++;
                        }
                        dPos++;
                        nPos++;
                    } while (dPos < divisorLen);

                    nPos = pos - divisorLen + 1;
                    dPos = 0;

                    // Overestimate
                    if (mc != 0)
                    {
                        uint_q_hat--;
                        ulong sum = 0;

                        do
                        {
                            sum             = remainder[nPos] + ((ulong)bi2.data[dPos]) + sum;
                            remainder[nPos] = (uint)sum;
                            sum           >>= 32;
                            dPos++;
                            nPos++;
                        } while (dPos < divisorLen);
                    }

                    quot.data[resultPos--] = uint_q_hat;

                    pos--;
                    j--;
                }

                quot.Normalize();
                rem.Normalize();
                var ret = new BigInteger[2] {
                    quot, rem
                };

                if (shift != 0)
                {
                    ret[1] >>= shift;
                }

                return(ret);
            }
Exemplo n.º 9
0
            public static BigInteger MultiplyByDword(BigInteger n, uint f)
            {
                var ret = new BigInteger(Sign.Positive, n.length + 1);

                uint i = 0;
                ulong c = 0;

                do
                {
                    c += n.data[i]*(ulong) f;
                    ret.data[i] = (uint) c;
                    c >>= 32;
                } while (++i < n.length);
                ret.data[i] = (uint) c;
                ret.Normalize();
                return ret;
            }
Exemplo n.º 10
0
            public static BigInteger Subtract(BigInteger big, BigInteger small)
            {
                var result = new BigInteger(Sign.Positive, big.length);

                uint[] r = result.data, b = big.data, s = small.data;
                uint i = 0, c = 0;

                do
                {
                    var x = s[i];
                    if (((x += c) < c) | ((r[i] = b[i] - x) > ~x))
                        c = 1;
                    else
                        c = 0;
                } while (++i < small.length);

                if (i == big.length) goto fixup;

                if (c == 1)
                {
                    do
                        r[i] = b[i] - 1; while (b[i++] == 0 && i < big.length);

                    if (i == big.length) goto fixup;
                }

                do
                    r[i] = b[i]; while (++i < big.length);

                fixup:

                result.Normalize();
                return result;
            }
Exemplo n.º 11
0
            /// <summary>
            ///     Adds two numbers with the same sign.
            /// </summary>
            /// <param name="bi1">A BigInteger</param>
            /// <param name="bi2">A BigInteger</param>
            /// <returns>bi1 + bi2</returns>
            public static BigInteger AddSameSign(BigInteger bi1, BigInteger bi2)
            {
                uint[] x, y;
                uint yMax, xMax, i = 0;

                // x should be bigger
                if (bi1.length < bi2.length)
                {
                    x = bi2.data;
                    xMax = bi2.length;
                    y = bi1.data;
                    yMax = bi1.length;
                }
                else
                {
                    x = bi1.data;
                    xMax = bi1.length;
                    y = bi2.data;
                    yMax = bi2.length;
                }

                var result = new BigInteger(Sign.Positive, xMax + 1);

                var r = result.data;

                ulong sum = 0;

                // Add common parts of both numbers
                do
                {
                    sum = x[i] + ((ulong) y[i]) + sum;
                    r[i] = (uint) sum;
                    sum >>= 32;
                } while (++i < yMax);

                // Copy remainder of longer number while carry propagation is required
                var carry = (sum != 0);

                if (carry)
                {
                    if (i < xMax)
                    {
                        do
                            carry = ((r[i] = x[i] + 1) == 0); while (++i < xMax && carry);
                    }

                    if (carry)
                    {
                        r[i] = 1;
                        result.length = ++i;
                        return result;
                    }
                }

                // Copy the rest
                if (i < xMax)
                {
                    do
                        r[i] = x[i]; while (++i < xMax);
                }

                result.Normalize();
                return result;
            }
Exemplo n.º 12
0
            public static void PlusEq(BigInteger bi1, BigInteger bi2)
            {
                uint[] x, y;
                uint yMax, xMax, i = 0;
                var flag = false;

                // x should be bigger
                if (bi1.length < bi2.length)
                {
                    flag = true;
                    x = bi2.data;
                    xMax = bi2.length;
                    y = bi1.data;
                    yMax = bi1.length;
                }
                else
                {
                    x = bi1.data;
                    xMax = bi1.length;
                    y = bi2.data;
                    yMax = bi2.length;
                }

                var r = bi1.data;

                ulong sum = 0;

                // Add common parts of both numbers
                do
                {
                    sum += x[i] + ((ulong) y[i]);
                    r[i] = (uint) sum;
                    sum >>= 32;
                } while (++i < yMax);

                // Copy remainder of longer number while carry propagation is required
                var carry = (sum != 0);

                if (carry)
                {
                    if (i < xMax)
                    {
                        do
                            carry = ((r[i] = x[i] + 1) == 0); while (++i < xMax && carry);
                    }

                    if (carry)
                    {
                        r[i] = 1;
                        bi1.length = ++i;
                        return;
                    }
                }

                // Copy the rest
                if (flag && i < xMax - 1)
                {
                    do
                        r[i] = x[i]; while (++i < xMax);
                }

                bi1.length = xMax + 1;
                bi1.Normalize();
            }
Exemplo n.º 13
0
            public static void PlusEq(BigInteger bi1, BigInteger bi2)
            {
                uint[] x, y;
                uint   yMax, xMax, i = 0;
                var    flag = false;

                // x should be bigger
                if (bi1.length < bi2.length)
                {
                    flag = true;
                    x    = bi2.data;
                    xMax = bi2.length;
                    y    = bi1.data;
                    yMax = bi1.length;
                }
                else
                {
                    x    = bi1.data;
                    xMax = bi1.length;
                    y    = bi2.data;
                    yMax = bi2.length;
                }

                var r = bi1.data;

                ulong sum = 0;

                // Add common parts of both numbers
                do
                {
                    sum  += x[i] + ((ulong)y[i]);
                    r[i]  = (uint)sum;
                    sum >>= 32;
                } while (++i < yMax);

                // Copy remainder of longer number while carry propagation is required
                var carry = (sum != 0);

                if (carry)
                {
                    if (i < xMax)
                    {
                        do
                        {
                            carry = ((r[i] = x[i] + 1) == 0);
                        } while (++i < xMax && carry);
                    }

                    if (carry)
                    {
                        r[i]       = 1;
                        bi1.length = ++i;
                        return;
                    }
                }

                // Copy the rest
                if (flag && i < xMax - 1)
                {
                    do
                    {
                        r[i] = x[i];
                    } while (++i < xMax);
                }

                bi1.length = xMax + 1;
                bi1.Normalize();
            }
Exemplo n.º 14
0
            /// <summary>
            ///     Performs n / d and n % d in one operation.
            /// </summary>
            /// <param name="n">A BigInteger, upon exit this will hold n / d</param>
            /// <param name="d">The divisor</param>
            /// <returns>n % d</returns>
            public static uint SingleByteDivideInPlace(BigInteger n, uint d)
            {
                ulong r = 0;
                var i = n.length;

                while (i-- > 0)
                {
                    r <<= 32;
                    r |= n.data[i];
                    n.data[i] = (uint) (r/d);
                    r %= d;
                }
                n.Normalize();

                return (uint) r;
            }
Exemplo n.º 15
0
            /// <summary>
            ///     Adds two numbers with the same sign.
            /// </summary>
            /// <param name="bi1">A BigInteger</param>
            /// <param name="bi2">A BigInteger</param>
            /// <returns>bi1 + bi2</returns>
            public static BigInteger AddSameSign(BigInteger bi1, BigInteger bi2)
            {
                uint[] x, y;
                uint   yMax, xMax, i = 0;

                // x should be bigger
                if (bi1.length < bi2.length)
                {
                    x    = bi2.data;
                    xMax = bi2.length;
                    y    = bi1.data;
                    yMax = bi1.length;
                }
                else
                {
                    x    = bi1.data;
                    xMax = bi1.length;
                    y    = bi2.data;
                    yMax = bi2.length;
                }

                var result = new BigInteger(Sign.Positive, xMax + 1);

                var r = result.data;

                ulong sum = 0;

                // Add common parts of both numbers
                do
                {
                    sum   = x[i] + ((ulong)y[i]) + sum;
                    r[i]  = (uint)sum;
                    sum >>= 32;
                } while (++i < yMax);

                // Copy remainder of longer number while carry propagation is required
                var carry = (sum != 0);

                if (carry)
                {
                    if (i < xMax)
                    {
                        do
                        {
                            carry = ((r[i] = x[i] + 1) == 0);
                        } while (++i < xMax && carry);
                    }

                    if (carry)
                    {
                        r[i]          = 1;
                        result.length = ++i;
                        return(result);
                    }
                }

                // Copy the rest
                if (i < xMax)
                {
                    do
                    {
                        r[i] = x[i];
                    } while (++i < xMax);
                }

                result.Normalize();
                return(result);
            }
Exemplo n.º 16
0
        public static BigInteger operator *(BigInteger bi1, BigInteger bi2)
        {
            if (bi1 == 0 || bi2 == 0) return 0;

            //
            // Validate pointers
            //
            if (bi1.data.Length < bi1.length) throw new IndexOutOfRangeException("bi1 out of range");
            if (bi2.data.Length < bi2.length) throw new IndexOutOfRangeException("bi2 out of range");

            var ret = new BigInteger(Sign.Positive, bi1.length + bi2.length);

            Kernel.Multiply(bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);

            ret.Normalize();
            return ret;
        }
Exemplo n.º 17
0
            public static BigInteger[] DwordDivMod(BigInteger n, uint d)
            {
                var ret = new BigInteger(Sign.Positive, n.length);

                ulong r = 0;
                var i = n.length;

                while (i-- > 0)
                {
                    r <<= 32;
                    r |= n.data[i];
                    ret.data[i] = (uint) (r/d);
                    r %= d;
                }
                ret.Normalize();

                BigInteger rem = (uint) r;

                return new[] {ret, rem};
            }
Exemplo n.º 18
0
            public static BigInteger RightShift(BigInteger bi, int n)
            {
                if (n == 0) return new BigInteger(bi);

                var w = n >> 5;
                var s = n & ((1 << 5) - 1);

                var ret = new BigInteger(Sign.Positive, bi.length - (uint) w + 1);
                var l = (uint) ret.data.Length - 1;

                if (s != 0)
                {
                    uint x, carry = 0;

                    while (l-- > 0)
                    {
                        x = bi.data[l + w];
                        ret.data[l] = (x >> n) | carry;
                        carry = x << (32 - n);
                    }
                }
                else
                {
                    while (l-- > 0)
                        ret.data[l] = bi.data[l + w];
                }
                ret.Normalize();
                return ret;
            }
Exemplo n.º 19
0
            public static BigInteger LeftShift(BigInteger bi, int n)
            {
                if (n == 0) return new BigInteger(bi, bi.length + 1);

                var w = n >> 5;
                n &= ((1 << 5) - 1);

                var ret = new BigInteger(Sign.Positive, bi.length + 1 + (uint) w);

                uint i = 0, l = bi.length;
                if (n != 0)
                {
                    uint x, carry = 0;
                    while (i < l)
                    {
                        x = bi.data[i];
                        ret.data[i + w] = (x << n) | carry;
                        carry = x >> (32 - n);
                        i++;
                    }
                    ret.data[i + w] = carry;
                }
                else
                {
                    while (i < l)
                    {
                        ret.data[i + w] = bi.data[i];
                        i++;
                    }
                }

                ret.Normalize();
                return ret;
            }
Exemplo n.º 20
0
            public static BigInteger[] multiByteDivide(BigInteger bi1, BigInteger bi2)
            {
                if (Compare(bi1, bi2) == Sign.Negative)
                    return new BigInteger[2] {0, new BigInteger(bi1)};

                bi1.Normalize();
                bi2.Normalize();

                if (bi2.length == 1)
                    return DwordDivMod(bi1, bi2.data[0]);

                var remainderLen = bi1.length + 1;
                var divisorLen = (int) bi2.length + 1;

                var mask = 0x80000000;
                var val = bi2.data[bi2.length - 1];
                var shift = 0;
                var resultPos = (int) bi1.length - (int) bi2.length;

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

                var quot = new BigInteger(Sign.Positive, bi1.length - bi2.length + 1);
                var rem = (bi1 << shift);

                var remainder = rem.data;

                bi2 = bi2 << shift;

                var j = (int) (remainderLen - bi2.length);
                var pos = (int) remainderLen - 1;

                var firstDivisorByte = bi2.data[bi2.length - 1];
                ulong secondDivisorByte = bi2.data[bi2.length - 2];

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

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

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

                            if (r_hat < 0x100000000)
                                continue;
                        }
                        break;
                    } while (true);

                    //
                    // At this point, q_hat is either exact, or one too large
                    // (more likely to be exact) so, we attempt to multiply the
                    // divisor by q_hat, if we get a borrow, we just subtract
                    // one from q_hat and add the divisor back.
                    //

                    uint t;
                    uint dPos = 0;
                    var nPos = pos - divisorLen + 1;
                    ulong mc = 0;
                    var uint_q_hat = (uint) q_hat;
                    do
                    {
                        mc += bi2.data[dPos]*(ulong) uint_q_hat;
                        t = remainder[nPos];
                        remainder[nPos] -= (uint) mc;
                        mc >>= 32;
                        if (remainder[nPos] > t) mc++;
                        dPos++;
                        nPos++;
                    } while (dPos < divisorLen);

                    nPos = pos - divisorLen + 1;
                    dPos = 0;

                    // Overestimate
                    if (mc != 0)
                    {
                        uint_q_hat--;
                        ulong sum = 0;

                        do
                        {
                            sum = remainder[nPos] + ((ulong) bi2.data[dPos]) + sum;
                            remainder[nPos] = (uint) sum;
                            sum >>= 32;
                            dPos++;
                            nPos++;
                        } while (dPos < divisorLen);
                    }

                    quot.data[resultPos--] = uint_q_hat;

                    pos--;
                    j--;
                }

                quot.Normalize();
                rem.Normalize();
                var ret = new BigInteger[2] {quot, rem};

                if (shift != 0)
                    ret[1] >>= shift;

                return ret;
            }
Exemplo n.º 21
0
            public void BarrettReduction(BigInteger x)
            {
                var  n         = mod;
                uint k         = n.length,
                     kPlusOne  = k + 1,
                     kMinusOne = k - 1;

                // x < mod, so nothing to do.
                if (x.length < k)
                {
                    return;
                }

                BigInteger q3;

                //
                // Validate pointers
                //
                if (x.data.Length < x.length)
                {
                    throw new IndexOutOfRangeException("x out of range");
                }

                // q1 = x / b^ (k-1)
                // q2 = q1 * constant
                // q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne

                // TODO: We should the method in HAC p 604 to do this (14.45)
                q3 = new BigInteger(Sign.Positive, x.length - kMinusOne + constant.length);
                Kernel.Multiply(x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);

                // r1 = x mod b^ (k+1)
                // i.e. keep the lowest (k+1) words

                var lengthToCopy = (x.length > kPlusOne) ? kPlusOne : x.length;

                x.length = lengthToCopy;
                x.Normalize();

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

                var r2 = new BigInteger(Sign.Positive, kPlusOne);

                Kernel.MultiplyMod2p32pmod(q3.data, (int)kPlusOne, (int)q3.length - (int)kPlusOne, n.data, 0,
                                           (int)n.length, r2.data, 0, (int)kPlusOne);

                r2.Normalize();

                if (r2 <= x)
                {
                    Kernel.MinusEq(x, r2);
                }
                else
                {
                    var val = new BigInteger(Sign.Positive, kPlusOne + 1);
                    val.data[kPlusOne] = 0x00000001;

                    Kernel.MinusEq(val, r2);
                    Kernel.PlusEq(x, val);
                }

                while (x >= n)
                {
                    Kernel.MinusEq(x, n);
                }
            }
Exemplo n.º 22
0
            public void BarrettReduction(BigInteger x)
            {
                var n = mod;
                uint k = n.length,
                    kPlusOne = k + 1,
                    kMinusOne = k - 1;

                // x < mod, so nothing to do.
                if (x.length < k) return;

                BigInteger q3;

                //
                // Validate pointers
                //
                if (x.data.Length < x.length) throw new IndexOutOfRangeException("x out of range");

                // q1 = x / b^ (k-1)
                // q2 = q1 * constant
                // q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne

                // TODO: We should the method in HAC p 604 to do this (14.45)
                q3 = new BigInteger(Sign.Positive, x.length - kMinusOne + constant.length);
                Kernel.Multiply(x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);

                // r1 = x mod b^ (k+1)
                // i.e. keep the lowest (k+1) words

                var lengthToCopy = (x.length > kPlusOne) ? kPlusOne : x.length;

                x.length = lengthToCopy;
                x.Normalize();

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

                var r2 = new BigInteger(Sign.Positive, kPlusOne);
                Kernel.MultiplyMod2p32pmod(q3.data, (int) kPlusOne, (int) q3.length - (int) kPlusOne, n.data, 0,
                    (int) n.length, r2.data, 0, (int) kPlusOne);

                r2.Normalize();

                if (r2 <= x)
                {
                    Kernel.MinusEq(x, r2);
                }
                else
                {
                    var val = new BigInteger(Sign.Positive, kPlusOne + 1);
                    val.data[kPlusOne] = 0x00000001;

                    Kernel.MinusEq(val, r2);
                    Kernel.PlusEq(x, val);
                }

                while (x >= n)
                    Kernel.MinusEq(x, n);
            }