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); }
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); }
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); }
// 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); }
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)); }
/// <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)); }
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()); }
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); } }
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; } }
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)); }
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); } }
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); } }
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); }
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); } }
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); }
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; } }
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); }