private static void PowCore(uint power, ref FastReducer reducer,
                                    ref BitsBuffer value, ref BitsBuffer result,
                                    ref BitsBuffer temp)
        {
            // The big modulus pow algorithm for the last or
            // the only power limb using square-and-multiply.

            // NOTE: we're using a special reducer here,
            // since it's additional overhead does pay off.

            while (power != 0)
            {
                if ((power & 1) == 1)
                {
                    result.MultiplySelf(ref value, ref temp);
                    result.Reduce(ref reducer);
                }
                if (power != 1)
                {
                    value.SquareSelf(ref temp);
                    value.Reduce(ref reducer);
                }
                power = power >> 1;
            }
        }
            public unsafe void MultiplySelf(ref BitsBuffer value,
                                            ref BitsBuffer temp)
            {
                Debug.Assert(temp._length == 0);
                Debug.Assert(_length + value._length <= temp._bits.Length);

                // Executes a multiplication for this and value, writes the
                // result to temp. Switches this and temp arrays afterwards.

                fixed (uint* b = _bits, v = value._bits, t = temp._bits)
                {
                    if (_length < value._length)
                    {
                        Multiply(v, value._length,
                                 b, _length,
                                 t, _length + value._length);
                    }
                    else
                    {
                        Multiply(b, _length,
                                 v, value._length,
                                 t, _length + value._length);
                    }
                }

                Apply(ref temp, _length + value._length);
            }
예제 #3
0
        public void BitBufferCanHandleLargeValuesAndCompression()
        {
            var values = GetFailingValues();

            using (var allocator = new ByteStringContext(SharedMultipleUseFlag.None))
                using (allocator.Allocate(2048, out var buffer))
                {
                    Memory.Set(buffer.Ptr, 0, buffer.Length);
                    var bitBuffer = new BitsBuffer(buffer.Ptr, buffer.Length);

                    var numberOfValues = values.Length;


                    for (int i = 0; i < numberOfValues; i++)
                    {
                        bitBuffer.EnsureAdditionalBits(allocator, values[i].Item2);
                        bitBuffer.AddValue(values[i].Item1, values[i].Item2);
                    }

                    using (bitBuffer.Uncompress(allocator, out var newBuf))
                    {
                        int offset = 0;
                        for (int i = 0; i < numberOfValues; i++)
                        {
                            var val = newBuf.ReadValue(ref offset, values[i].Item2);
                            if (val != values[i].Item1)
                            {
                                Assert.False(true, "Unmatch value at index: " + i);
                            }
                        }
                    }
                }
        }
        private static void LehmerCore(ref BitsBuffer xBuffer,
                                       ref BitsBuffer yBuffer,
                                       long a, long b,
                                       long c, long d)
        {
            Debug.Assert(xBuffer.GetLength() >= 1);
            Debug.Assert(yBuffer.GetLength() >= 1);
            Debug.Assert(xBuffer.GetLength() >= yBuffer.GetLength());
            Debug.Assert(a <= 0x7FFFFFFF && b <= 0x7FFFFFFF);
            Debug.Assert(c <= 0x7FFFFFFF && d <= 0x7FFFFFFF);

            // Executes the combined calculation of Lehmer's step.

            uint[] x = xBuffer.GetBits();
            uint[] y = yBuffer.GetBits();

            int length = yBuffer.GetLength();

            long xCarry = 0L, yCarry = 0L;

            for (int i = 0; i < length; i++)
            {
                long xDigit = a * x[i] - b * y[i] + xCarry;
                long yDigit = d * y[i] - c * x[i] + yCarry;
                xCarry = xDigit >> 32;
                yCarry = yDigit >> 32;
                x[i]   = unchecked ((uint)xDigit);
                y[i]   = unchecked ((uint)yDigit);
            }

            xBuffer.Refresh(length);
            yBuffer.Refresh(length);
        }
        private static void PowCore(uint[] power, ref FastReducer reducer,
                                    ref BitsBuffer value, ref BitsBuffer result,
                                    ref BitsBuffer temp)
        {
            // The big modulus pow algorithm for all but
            // the last power limb using square-and-multiply.

            // NOTE: we're using a special reducer here,
            // since it's additional overhead does pay off.

            for (int i = 0; i < power.Length - 1; i++)
            {
                uint p = power[i];
                for (int j = 0; j < 32; j++)
                {
                    if ((p & 1) == 1)
                    {
                        result.MultiplySelf(ref value, ref temp);
                        result.Reduce(ref reducer);
                    }
                    value.SquareSelf(ref temp);
                    value.Reduce(ref reducer);
                    p = p >> 1;
                }
            }

            PowCore(power[power.Length - 1], ref reducer, ref value, ref result,
                    ref temp);
        }
        private static void PowCore(uint power, uint[] modulus,
                                    ref BitsBuffer value, ref BitsBuffer result,
                                    ref BitsBuffer temp)
        {
            // The big modulus pow algorithm for the last or
            // the only power limb using square-and-multiply.

            // NOTE: we're using an ordinary remainder here,
            // since the reducer overhead doesn't pay off.

            while (power != 0)
            {
                if ((power & 1) == 1)
                {
                    result.MultiplySelf(ref value, ref temp);
                    result.Reduce(modulus);
                }
                if (power != 1)
                {
                    value.SquareSelf(ref temp);
                    value.Reduce(modulus);
                }
                power = power >> 1;
            }
        }
            public unsafe void MultiplySelf(ref BitsBuffer value,
                                            ref BitsBuffer temp)
            {
                Debug.Assert(temp._length == 0);
                Debug.Assert(_length + value._length <= temp._bits.Length);

                // Executes a multiplication for this and value, writes the
                // result to temp. Switches this and temp arrays afterwards.

                fixed(uint *b = _bits, v = value._bits, t = temp._bits)
                {
                    if (_length < value._length)
                    {
                        Multiply(v, value._length,
                                 b, _length,
                                 t, _length + value._length);
                    }
                    else
                    {
                        Multiply(b, _length,
                                 v, value._length,
                                 t, _length + value._length);
                    }
                }

                Apply(ref temp, _length + value._length);
            }
예제 #8
0
        public unsafe void BitBufferCompression()
        {
            using (var allocator = new ByteStringContext(SharedMultipleUseFlag.None))
                using (allocator.Allocate(2048, out var buffer))
                {
                    Memory.Set(buffer.Ptr, 0, buffer.Length);
                    var bitBuffer = new BitsBuffer(buffer.Ptr, buffer.Length);

                    for (int i = 0; i < 12; i++)
                    {
                        bitBuffer.AddValue((ulong)(i & 1), 1);
                    }

                    bitBuffer.TryCompressBuffer(allocator, 0);


                    bitBuffer.Uncompress(allocator, out var newBuffer);

                    for (int i = 0; i < 12; i++)
                    {
                        int copy = i;
                        var v    = newBuffer.ReadValue(ref copy, 1);
                        Assert.Equal((ulong)(i & 1), v);
                    }
                }
        }
        private static void ExtractDigits(ref BitsBuffer xBuffer,
                                          ref BitsBuffer yBuffer,
                                          out ulong x, out ulong y)
        {
            Debug.Assert(xBuffer.GetLength() >= 3);
            Debug.Assert(yBuffer.GetLength() >= 3);
            Debug.Assert(xBuffer.GetLength() >= yBuffer.GetLength());

            // Extracts the most significant bits of x and y,
            // but ensures the quotient x / y does not change!

            uint[] xBits   = xBuffer.GetBits();
            int    xLength = xBuffer.GetLength();

            uint[] yBits   = yBuffer.GetBits();
            int    yLength = yBuffer.GetLength();

            ulong xh = xBits[xLength - 1];
            ulong xm = xBits[xLength - 2];
            ulong xl = xBits[xLength - 3];

            ulong yh, ym, yl;

            // arrange the bits
            switch (xLength - yLength)
            {
            case 0:
                yh = yBits[yLength - 1];
                ym = yBits[yLength - 2];
                yl = yBits[yLength - 3];
                break;

            case 1:
                yh = 0UL;
                ym = yBits[yLength - 1];
                yl = yBits[yLength - 2];
                break;

            case 2:
                yh = 0UL;
                ym = 0UL;
                yl = yBits[yLength - 1];
                break;

            default:
                yh = 0UL;
                ym = 0UL;
                yl = 0UL;
                break;
            }

            // Use all the bits but one, see [hac] 14.58 (ii)
            int z = LeadingZeros((uint)xh);

            x = ((xh << 32 + z) | (xm << z) | (xl >> 32 - z)) >> 1;
            y = ((yh << 32 + z) | (ym << z) | (yl >> 32 - z)) >> 1;

            Debug.Assert(x >= y);
        }
예제 #10
0
        // Executes different exponentiation algorithms, which are
        // basically based on the classic square-and-multiply method.

        // https://en.wikipedia.org/wiki/Exponentiation_by_squaring

        public static uint[] Pow(uint value, uint power)
        {
            // The basic pow method for a 32-bit integer.
            // To spare memory allocations we first roughly
            // estimate an upper bound for our buffers.

            int size = PowBound(power, 1, 1);
            BitsBuffer v = new BitsBuffer(size, value);
            return PowCore(power, ref v);
        }
        public static uint[] Pow(uint[] value, uint power)
        {
            Debug.Assert(value != null);

            // The basic pow method for a big integer.
            // To spare memory allocations we first roughly
            // estimate an upper bound for our buffers.
            int size = PowBound(power, value.Length, 1);
            BitsBuffer v = new BitsBuffer(size, value);
            return PowCore(power, ref v);
        }
예제 #12
0
        public static uint[] Pow(uint value, uint power, uint[] modulus)
        {
            Debug.Assert(modulus != null);

            // The big modulus pow method for a 32-bit integer
            // raised by a 32-bit integer...
            int        size = modulus.Length + modulus.Length;
            BitsBuffer v    = new BitsBuffer(size, value);

            return(PowCore(power, modulus, ref v));
        }
예제 #13
0
        /// <summary>
        /// Executes different exponentiation algorithms, which are
        /// basically based on the classic square-and-multiply method.
        /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
        /// </summary>
        public static uint[] Pow(uint value, uint power)
        {
            // The basic pow method for a 32-bit integer.
            // To spare memory allocations we first roughly
            // estimate an upper bound for our buffers.

            int        size = PowBound(power, 1, 1);
            BitsBuffer v    = new BitsBuffer(size, value);

            return(PowCore(power, ref v));
        }
예제 #14
0
        private static uint[] PowCore(uint power, ref BitsBuffer value)
        {
            // Executes the basic pow algorithm.
            int size = value.GetSize();

            BitsBuffer temp   = new BitsBuffer(size, 0);
            BitsBuffer result = new BitsBuffer(size, 1);

            PowCore(power, ref value, ref result, ref temp);

            return(result.GetBits());
        }
예제 #15
0
        public static uint[] Pow(uint[] value, uint power)
        {
            Debug.Assert(value != null);

            // The basic pow method for a big integer.
            // To spare memory allocations we first roughly
            // estimate an upper bound for our buffers.
            int        size = PowBound(power, value.Length, 1);
            BitsBuffer v    = new BitsBuffer(size, value);

            return(PowCore(power, ref v));
        }
        private static uint[] PowCore(uint power, ref BitsBuffer value)
        {
            // Executes the basic pow algorithm.
            int size = value.GetSize();

            BitsBuffer temp = new BitsBuffer(size, 0);
            BitsBuffer result = new BitsBuffer(size, 1);

            PowCore(power, ref value, ref result, ref temp);

            return result.GetBits();
        }
 private static void PowCore(uint power, ref BitsBuffer value,
                             ref BitsBuffer result, ref BitsBuffer temp)
 {
     // The basic pow algorithm using square-and-multiply.
     while (power != 0)
     {
         if ((power & 1) == 1)
             result.MultiplySelf(ref value, ref temp);
         if (power != 1)
             value.SquareSelf(ref temp);
         power = power >> 1;
     }
 }
            private void Apply(ref BitsBuffer temp, int maxLength)
            {
                Debug.Assert(temp._length == 0);
                Debug.Assert(maxLength <= temp._bits.Length);

                // Resets this and switches this and temp afterwards.
                // The caller assumed an empty temp, the next will too.
                Array.Clear(_bits, 0, _length);

                uint[] t = temp._bits;
                temp._bits = _bits;
                _bits      = t;

                _length = ActualLength(_bits, maxLength);
            }
        public static uint[] Gcd(uint[] left, uint[] right)
        {
            Debug.Assert(left != null);
            Debug.Assert(left.Length >= 2);
            Debug.Assert(right != null);
            Debug.Assert(right.Length >= 2);
            Debug.Assert(Compare(left, right) >= 0);

            BitsBuffer leftBuffer = new BitsBuffer(left.Length, left);
            BitsBuffer rightBuffer = new BitsBuffer(right.Length, right);

            Gcd(ref leftBuffer, ref rightBuffer);

            return leftBuffer.GetBits();
        }
        public static uint[] Gcd(uint[] left, uint[] right)
        {
            Debug.Assert(left != null);
            Debug.Assert(left.Length >= 2);
            Debug.Assert(right != null);
            Debug.Assert(right.Length >= 2);
            Debug.Assert(Compare(left, right) >= 0);

            BitsBuffer leftBuffer  = new BitsBuffer(left.Length, left);
            BitsBuffer rightBuffer = new BitsBuffer(right.Length, right);

            Gcd(ref leftBuffer, ref rightBuffer);

            return(leftBuffer.GetBits());
        }
            public unsafe void SquareSelf(ref BitsBuffer temp)
            {
                Debug.Assert(temp._length == 0);
                Debug.Assert(_length + _length <= temp._bits.Length);

                // Executes a square for this, writes the result to temp.
                // Switches this and temp arrays afterwards.

                fixed(uint *b = _bits, t = temp._bits)
                {
                    Square(b, _length,
                           t, _length + _length);
                }

                Apply(ref temp, _length + _length);
            }
            public unsafe void SquareSelf(ref BitsBuffer temp)
            {
                Debug.Assert(temp._length == 0);
                Debug.Assert(_length + _length <= temp._bits.Length);

                // Executes a square for this, writes the result to temp.
                // Switches this and temp arrays afterwards.

                fixed (uint* b = _bits, t = temp._bits)
                {
                    Square(b, _length,
                           t, _length + _length);
                }

                Apply(ref temp, _length + _length);
            }
            public unsafe void Reduce(ref BitsBuffer modulus)
            {
                // Executes a modulo operation using the divide operation.
                // Thus, no need of any switching here, happens in-line.
                if (_length >= modulus._length)
                {
                    fixed(uint *b = _bits, m = modulus._bits)
                    {
                        Divide(b, _length,
                               m, modulus._length,
                               null, 0);
                    }

                    _length = ActualLength(_bits, modulus._length);
                }
            }
예제 #24
0
 private static void PowCore(uint power, ref BitsBuffer value,
                             ref BitsBuffer result, ref BitsBuffer temp)
 {
     // The basic pow algorithm using square-and-multiply.
     while (power != 0)
     {
         if ((power & 1) == 1)
         {
             result.MultiplySelf(ref value, ref temp);
         }
         if (power != 1)
         {
             value.SquareSelf(ref temp);
         }
         power = power >> 1;
     }
 }
예제 #25
0
        public void CanSetBits()
        {
            var buffer      = stackalloc byte[16];
            var bitsBufffer = new BitsBuffer(buffer, 16);

            bitsBufffer.AddValue(12, 6);
            bitsBufffer.AddValue(3, 7);
            bitsBufffer.AddValue(279, 18);

            bitsBufffer.SetBits(6, 7, 7);

            int index = 0;

            Assert.Equal(12UL, bitsBufffer.ReadValue(ref index, 6));
            Assert.Equal(7UL, bitsBufffer.ReadValue(ref index, 7));
            Assert.Equal(279UL, bitsBufffer.ReadValue(ref index, 18));
        }
        public static uint[] Pow(uint[] value, uint[] power, uint[] modulus)
        {
            Debug.Assert(value != null);
            Debug.Assert(power != null);
            Debug.Assert(modulus != null);

            // The big modulus pow method for a big integer
            // raised by a big integer...

            if (value.Length > modulus.Length)
            {
                value = Remainder(value, modulus);
            }

            int        size = modulus.Length + modulus.Length;
            BitsBuffer v    = new BitsBuffer(size, value);

            return(PowCore(power, modulus, ref v));
        }
예제 #27
0
        private static uint[] PowCore(uint power, uint[] modulus,
                                      ref BitsBuffer value)
        {
            // Executes the big pow algorithm.
            int size = value.GetSize();

            BitsBuffer temp   = new BitsBuffer(size, 0);
            BitsBuffer result = new BitsBuffer(size, 1);

            if (modulus.Length < ReducerThreshold)
            {
                PowCore(power, modulus, ref value, ref result, ref temp);
            }
            else
            {
                FastReducer reducer = new FastReducer(modulus);
                PowCore(power, ref reducer, ref value, ref result, ref temp);
            }

            return(result.GetBits());
        }
        public static byte[] Encode(IEnumerable <byte> data, out Dictionary <BitsWithLength, byte> decodeTable,
                                    out long bitsCount)
        {
            var dArr       = data.ToArray();
            var frequences = CalcFrequences(dArr);

            var root = BuildHuffmanTree(frequences);

            var encodeTable = new BitsWithLength[byte.MaxValue + 1];

            FillEncodeTable(root, encodeTable);

            var bitsBuffer = new BitsBuffer();

            foreach (var b in dArr)
            {
                bitsBuffer.Add(encodeTable[b]);
            }

            decodeTable = CreateDecodeTable(encodeTable);

            return(bitsBuffer.ToArray(out bitsCount));
        }
        private static void Gcd(ref BitsBuffer left, ref BitsBuffer right)
        {
            Debug.Assert(left.GetLength() >= 2);
            Debug.Assert(right.GetLength() >= 2);
            Debug.Assert(left.GetLength() >= right.GetLength());

            // Executes Lehmer's gcd algorithm, but uses the most 
            // significant bits to work with 64-bit (not 32-bit) values.
            // Furthermore we're using an optimized version due to Jebelean.

            // http://cacr.uwaterloo.ca/hac/about/chap14.pdf (see 14.4.2)
            // ftp://ftp.risc.uni-linz.ac.at/pub/techreports/1992/92-69.ps.gz

            while (right.GetLength() > 2)
            {
                ulong x, y;

                ExtractDigits(ref left, ref right, out x, out y);

                uint a = 1U, b = 0U;
                uint c = 0U, d = 1U;

                int iteration = 0;

                // Lehmer's guessing
                while (y != 0)
                {
                    ulong q, r, s, t;

                    // odd iteration
                    q = x / y;

                    if (q > 0xFFFFFFFF)
                        break;

                    r = a + q * c;
                    s = b + q * d;
                    t = x - q * y;

                    if (r > 0x7FFFFFFF || s > 0x7FFFFFFF)
                        break;
                    if (t < s || t + r > y - c)
                        break;

                    a = (uint)r;
                    b = (uint)s;
                    x = t;

                    ++iteration;
                    if (x == b)
                        break;

                    // even iteration
                    q = y / x;

                    if (q > 0xFFFFFFFF)
                        break;

                    r = d + q * b;
                    s = c + q * a;
                    t = y - q * x;

                    if (r > 0x7FFFFFFF || s > 0x7FFFFFFF)
                        break;
                    if (t < s || t + r > x - b)
                        break;

                    d = (uint)r;
                    c = (uint)s;
                    y = t;

                    ++iteration;
                    if (y == c)
                        break;
                }

                if (b == 0)
                {
                    // Euclid's step
                    left.Reduce(ref right);

                    BitsBuffer temp = left;
                    left = right;
                    right = temp;
                }
                else
                {
                    // Lehmer's step
                    LehmerCore(ref left, ref right, a, b, c, d);

                    if (iteration % 2 == 1)
                    {
                        // ensure left is larger than right
                        BitsBuffer temp = left;
                        left = right;
                        right = temp;
                    }
                }
            }

            if (right.GetLength() > 0)
            {
                // Euclid's step
                left.Reduce(ref right);

                uint[] xBits = right.GetBits();
                uint[] yBits = left.GetBits();

                ulong x = ((ulong)xBits[1] << 32) | xBits[0];
                ulong y = ((ulong)yBits[1] << 32) | yBits[0];

                left.Overwrite(Gcd(x, y));
                right.Overwrite(0);
            }
        }
예제 #30
0
        private static uint[] PowCore(uint power, uint[] modulus,
                                      ref BitsBuffer value)
        {
            // Executes the big pow algorithm.

            int size = value.GetSize();

            BitsBuffer temp = new BitsBuffer(size, 0);
            BitsBuffer result = new BitsBuffer(size, 1);

            if (modulus.Length < ReducerThreshold)
            {
                PowCore(power, modulus, ref value, ref result, ref temp);
            }
            else
            {
                FastReducer reducer = new FastReducer(modulus);
                PowCore(power, ref reducer, ref value, ref result, ref temp);
            }

            return result.GetBits();
        }
        private static void LehmerCore(ref BitsBuffer xBuffer,
                                       ref BitsBuffer yBuffer,
                                       long a, long b,
                                       long c, long d)
        {
            Debug.Assert(xBuffer.GetLength() >= 1);
            Debug.Assert(yBuffer.GetLength() >= 1);
            Debug.Assert(xBuffer.GetLength() >= yBuffer.GetLength());
            Debug.Assert(a <= 0x7FFFFFFF && b <= 0x7FFFFFFF);
            Debug.Assert(c <= 0x7FFFFFFF && d <= 0x7FFFFFFF);

            // Executes the combined calculation of Lehmer's step.

            uint[] x = xBuffer.GetBits();
            uint[] y = yBuffer.GetBits();

            int length = yBuffer.GetLength();

            long xCarry = 0L, yCarry = 0L;
            for (int i = 0; i < length; i++)
            {
                long xDigit = a * x[i] - b * y[i] + xCarry;
                long yDigit = d * y[i] - c * x[i] + yCarry;
                xCarry = xDigit >> 32;
                yCarry = yDigit >> 32;
                x[i] = (uint)xDigit;
                y[i] = (uint)yDigit;
            }

            xBuffer.Refresh(length);
            yBuffer.Refresh(length);
        }
        private static void ExtractDigits(ref BitsBuffer xBuffer,
                                          ref BitsBuffer yBuffer,
                                          out ulong x, out ulong y)
        {
            Debug.Assert(xBuffer.GetLength() >= 3);
            Debug.Assert(yBuffer.GetLength() >= 3);
            Debug.Assert(xBuffer.GetLength() >= yBuffer.GetLength());

            // Extracts the most significant bits of x and y,
            // but ensures the quotient x / y does not change!

            uint[] xBits = xBuffer.GetBits();
            int xLength = xBuffer.GetLength();

            uint[] yBits = yBuffer.GetBits();
            int yLength = yBuffer.GetLength();

            ulong xh = xBits[xLength - 1];
            ulong xm = xBits[xLength - 2];
            ulong xl = xBits[xLength - 3];

            ulong yh, ym, yl;

            // arrange the bits
            switch (xLength - yLength)
            {
                case 0:
                    yh = yBits[yLength - 1];
                    ym = yBits[yLength - 2];
                    yl = yBits[yLength - 3];
                    break;

                case 1:
                    yh = 0UL;
                    ym = yBits[yLength - 1];
                    yl = yBits[yLength - 2];
                    break;

                case 2:
                    yh = 0UL;
                    ym = 0UL;
                    yl = yBits[yLength - 1];
                    break;

                default:
                    yh = 0UL;
                    ym = 0UL;
                    yl = 0UL;
                    break;
            }

            // use all the bits but one, see [hac] 14.58 (ii)
            int z = LeadingZeros((uint)xh);

            x = ((xh << 32 + z) | (xm << z) | (xl >> 32 - z)) >> 1;
            y = ((yh << 32 + z) | (ym << z) | (yl >> 32 - z)) >> 1;

            Debug.Assert(x >= y);
        }
        private static void Gcd(ref BitsBuffer left, ref BitsBuffer right)
        {
            Debug.Assert(left.GetLength() >= 2);
            Debug.Assert(right.GetLength() >= 2);
            Debug.Assert(left.GetLength() >= right.GetLength());

            // Executes Lehmer's gcd algorithm, but uses the most
            // significant bits to work with 64-bit (not 32-bit) values.
            // Furthermore we're using an optimized version due to Jebelean.

            // http://cacr.uwaterloo.ca/hac/about/chap14.pdf (see 14.4.2)
            // ftp://ftp.risc.uni-linz.ac.at/pub/techreports/1992/92-69.ps.gz

            while (right.GetLength() > 2)
            {
                ulong x, y;

                ExtractDigits(ref left, ref right, out x, out y);

                uint a = 1U, b = 0U;
                uint c = 0U, d = 1U;

                int iteration = 0;

                // Lehmer's guessing
                while (y != 0)
                {
                    ulong q, r, s, t;

                    // Odd iteration
                    q = x / y;

                    if (q > 0xFFFFFFFF)
                    {
                        break;
                    }

                    r = a + q * c;
                    s = b + q * d;
                    t = x - q * y;

                    if (r > 0x7FFFFFFF || s > 0x7FFFFFFF)
                    {
                        break;
                    }
                    if (t < s || t + r > y - c)
                    {
                        break;
                    }

                    a = (uint)r;
                    b = (uint)s;
                    x = t;

                    ++iteration;
                    if (x == b)
                    {
                        break;
                    }

                    // Even iteration
                    q = y / x;

                    if (q > 0xFFFFFFFF)
                    {
                        break;
                    }

                    r = d + q * b;
                    s = c + q * a;
                    t = y - q * x;

                    if (r > 0x7FFFFFFF || s > 0x7FFFFFFF)
                    {
                        break;
                    }
                    if (t < s || t + r > x - b)
                    {
                        break;
                    }

                    d = (uint)r;
                    c = (uint)s;
                    y = t;

                    ++iteration;
                    if (y == c)
                    {
                        break;
                    }
                }

                if (b == 0)
                {
                    // Euclid's step
                    left.Reduce(ref right);

                    BitsBuffer temp = left;
                    left  = right;
                    right = temp;
                }
                else
                {
                    // Lehmer's step
                    LehmerCore(ref left, ref right, a, b, c, d);

                    if (iteration % 2 == 1)
                    {
                        // Ensure left is larger than right
                        BitsBuffer temp = left;
                        left  = right;
                        right = temp;
                    }
                }
            }

            if (right.GetLength() > 0)
            {
                // Euclid's step
                left.Reduce(ref right);

                uint[] xBits = right.GetBits();
                uint[] yBits = left.GetBits();

                ulong x = ((ulong)xBits[1] << 32) | xBits[0];
                ulong y = ((ulong)yBits[1] << 32) | yBits[0];

                left.Overwrite(Gcd(x, y));
                right.Overwrite(0);
            }
        }
예제 #34
0
        public static uint[] Pow(uint value, uint power, uint[] modulus)
        {
            Debug.Assert(modulus != null);

            // The big modulus pow method for a 32-bit integer
            // raised by a 32-bit integer...

            int size = modulus.Length + modulus.Length;
            BitsBuffer v = new BitsBuffer(size, value);
            return PowCore(power, modulus, ref v);
        }
예제 #35
0
        private static void PowCore(uint power, ref FastReducer reducer,
                                    ref BitsBuffer value, ref BitsBuffer result,
                                    ref BitsBuffer temp)
        {
            // The big modulus pow algorithm for the last or
            // the only power limb using square-and-multiply.

            // NOTE: we're using a special reducer here,
            // since it's additional overhead does pay off.

            while (power != 0)
            {
                if ((power & 1) == 1)
                {
                    result.MultiplySelf(ref value, ref temp);
                    result.Reduce(ref reducer);
                }
                if (power != 1)
                {
                    value.SquareSelf(ref temp);
                    value.Reduce(ref reducer);
                }
                power = power >> 1;
            }
        }
            public unsafe void Reduce(ref BitsBuffer modulus)
            {
                // Executes a modulo operation using the divide operation.
                // Thus, no need of any switching here, happens in-line.

                if (_length >= modulus._length)
                {
                    fixed (uint* b = _bits, m = modulus._bits)
                    {
                        Divide(b, _length,
                               m, modulus._length,
                               null, 0);
                    }

                    _length = ActualLength(_bits, modulus._length);
                }
            }
예제 #37
0
        public static uint[] Pow(uint[] value, uint[] power, uint[] modulus)
        {
            Debug.Assert(value != null);
            Debug.Assert(power != null);
            Debug.Assert(modulus != null);

            // The big modulus pow method for a big integer
            // raised by a big integer...

            if (value.Length > modulus.Length)
                value = Remainder(value, modulus);

            int size = modulus.Length + modulus.Length;
            BitsBuffer v = new BitsBuffer(size, value);
            return PowCore(power, modulus, ref v);
        }
예제 #38
0
        private static void PowCore(uint[] power, ref FastReducer reducer,
                                    ref BitsBuffer value, ref BitsBuffer result,
                                    ref BitsBuffer temp)
        {
            // The big modulus pow algorithm for all but
            // the last power limb using square-and-multiply.

            // NOTE: we're using a special reducer here,
            // since it's additional overhead does pay off.

            for (int i = 0; i < power.Length - 1; i++)
            {
                uint p = power[i];
                for (int j = 0; j < 32; j++)
                {
                    if ((p & 1) == 1)
                    {
                        result.MultiplySelf(ref value, ref temp);
                        result.Reduce(ref reducer);
                    }
                    value.SquareSelf(ref temp);
                    value.Reduce(ref reducer);
                    p = p >> 1;
                }
            }

            PowCore(power[power.Length - 1], ref reducer, ref value, ref result,
                ref temp);
        }
예제 #39
0
        private static void PowCore(uint power, uint[] modulus,
                                    ref BitsBuffer value, ref BitsBuffer result,
                                    ref BitsBuffer temp)
        {
            // The big modulus pow algorithm for the last or
            // the only power limb using square-and-multiply.

            // NOTE: we're using an ordinary remainder here,
            // since the reducer overhead doesn't pay off.

            while (power != 0)
            {
                if ((power & 1) == 1)
                {
                    result.MultiplySelf(ref value, ref temp);
                    result.Reduce(modulus);
                }
                if (power != 1)
                {
                    value.SquareSelf(ref temp);
                    value.Reduce(modulus);
                }
                power = power >> 1;
            }
        }
            private void Apply(ref BitsBuffer temp, int maxLength)
            {
                Debug.Assert(temp._length == 0);
                Debug.Assert(maxLength <= temp._bits.Length);

                // Resets this and switches this and temp afterwards.
                // The caller assumed an empty temp, the next will too.

                Array.Clear(_bits, 0, _length);

                uint[] t = temp._bits;
                temp._bits = _bits;
                _bits = t;

                _length = ActualLength(_bits, maxLength);
            }