private void OptimizeInternal(int size, Trie <T>[] children) { var smallChildren = new Trie <T> [size]; Mask = int.MaxValue >> 31 - Bits.CeilLog2(size); foreach (var trie in children) { var key = trie.Key[0] & Mask; if (smallChildren[key] != null) { if (smallChildren[key] == trie) { break; // different casing, same val, nothing to do } // real collision, double the size and try again OptimizeInternal(size * 2, children); return; } trie.DebugKey = DebugKey + trie.Key; smallChildren[key] = trie; trie.Optimize(); } Children = smallChildren; }
public PageLocatorCurrent(LowLevelTransactionStub tx, int cacheSize = 8) { //Debug.Assert(tx != null); //Debug.Assert(cacheSize > 0); _tx = tx; if (tx != null) { Debug.Fail(""); } cacheSize = Bits.NextPowerOf2(cacheSize); if (cacheSize > 1024) { cacheSize = 1024; } int shiftRight = Bits.CeilLog2(cacheSize); _andMask = (int)(0xFFFFFFFF >> (sizeof(uint) * 8 - shiftRight)); _tx = tx; _allocator.Allocate(cacheSize * sizeof(PageData), out _cacheMemory); _cache = (PageData *)_cacheMemory.Ptr; for (var i = 0; i < cacheSize; i++) { _cache[i].PageNumber = Invalid; } }
public void Renew(LowLevelTransaction tx, int cacheSize) { Debug.Assert(tx != null); Debug.Assert(cacheSize > 0); Debug.Assert(cacheSize <= 1024); if (!Bits.IsPowerOfTwo(cacheSize)) { cacheSize = Bits.NextPowerOf2(cacheSize); } int shiftRight = Bits.CeilLog2(cacheSize); _andMask = (int)(0xFFFFFFFF >> (sizeof(uint) * 8 - shiftRight)); _tx = tx; tx.Allocator.Allocate(cacheSize * sizeof(PageData), out _cacheMemory); _cache = (PageData *)_cacheMemory.Ptr; for (var i = 0; i < cacheSize; i++) { _cache[i].PageNumber = Invalid; } }
/// <summary> /// Converts <see cref="IntX" /> digits into real representation (used in FHT). /// </summary> /// <param name="digitsPtr">Big integer digits.</param> /// <param name="length"><paramref name="digitsPtr" /> length.</param> /// <param name="newLength">Multiplication result length (must be pow of 2).</param> /// <returns>Double array.</returns> static public double[] ConvertDigitsToDouble(uint *digitsPtr, uint length, uint newLength) { // Maybe fix newLength (make it the nearest bigger pow of 2) newLength = 1U << Bits.CeilLog2(newLength); // For better FHT accuracy we will choose length smaller then dwords. // So new length must be modified accordingly newLength <<= DoubleDataLengthShift; double[] data = ArrayPool <double> .Instance.GetArray(newLength); // Run in unsafe context fixed(double *slice = data) { // Amount of units pointed by digitsPtr uint unitCount = length << DoubleDataLengthShift; // Copy all words from digits into new double[] byte *unitDigitsPtr = (byte *)digitsPtr; for (uint i = 0; i < unitCount; ++i) { slice[i] = unitDigitsPtr[i]; } // Clear remaining double values (this array is from pool and may be dirty) DigitHelper.SetBlockDigits(slice + unitCount, newLength - unitCount, 0.0); // FHT (as well as FFT) works more accurate with "balanced" data, so let's balance it double carry = 0, dataDigit; for (uint i = 0; i < unitCount || i < newLength && carry != 0; ++i) { dataDigit = slice[i] + carry; if (dataDigit >= DoubleDataBaseDiv2) { dataDigit -= DoubleDataBase; carry = 1.0; } else { carry = 0; } slice[i] = dataDigit; } if (carry > 0) { slice[0] -= carry; } } return(data); }
public void Bits_Ceil2Log() { Assert.Equal(0, Bits.CeilLog2(0)); Assert.Equal(0, Bits.CeilLog2(1)); Assert.Equal(1, Bits.CeilLog2(2)); Assert.Equal(2, Bits.CeilLog2(3)); Assert.Equal(2, Bits.CeilLog2(4)); Assert.Equal(16, Bits.CeilLog2(0x0000FF00)); Assert.Equal(31, Bits.CeilLog2(0x40B79DF0)); Assert.Equal(0, Bits.CeilLog2((uint)0)); Assert.Equal(0, Bits.CeilLog2((uint)1)); Assert.Equal(1, Bits.CeilLog2((uint)2)); Assert.Equal(2, Bits.CeilLog2((uint)3)); Assert.Equal(2, Bits.CeilLog2((uint)4)); Assert.Equal(16, Bits.CeilLog2((uint)0x0000FF00)); Assert.Equal(32, Bits.CeilLog2((uint)0xFFFF0000)); Assert.Equal(31, Bits.CeilLog2((uint)0x40B79DF0)); }
private static int CalculateCompressionAcceleration(int size) { return(Bits.CeilLog2(size)); }
/// <summary> /// Generates integer opposite to the given one using approximation. /// Uses algorithm from Khuth vol. 2 3rd Edition (4.3.3). /// </summary> /// <param name="digitsPtr">Initial big integer digits.</param> /// <param name="length">Initial big integer length.</param> /// <param name="maxLength">Precision length.</param> /// <param name="bufferPtr">Buffer in which shifted big integer may be stored.</param> /// <param name="newLength">Resulting big integer length.</param> /// <param name="rightShift">How much resulting big integer is shifted to the left (or: must be shifted to the right).</param> /// <returns>Resulting big integer digits.</returns> static unsafe public uint[] GetIntegerOpposite( uint *digitsPtr, uint length, uint maxLength, uint *bufferPtr, out uint newLength, out ulong rightShift) { // Maybe initially shift original digits a bit to the left // (it must have MSB on 2nd position in the highest digit) int msb = Bits.Msb(digitsPtr[length - 1]); rightShift = (ulong)(length - 1) * Constants.DigitBitCount + (ulong)msb + 1U; if (msb != 2) { // Shift to the left (via actually right shift) int leftShift = (2 - msb + Constants.DigitBitCount) % Constants.DigitBitCount; length = DigitOpHelper.Shr(digitsPtr, length, bufferPtr + 1, Constants.DigitBitCount - leftShift, true) + 1U; } else { // Simply use the same digits without any shifting bufferPtr = digitsPtr; } // Calculate possible result length int lengthLog2 = Bits.CeilLog2(maxLength); uint newLengthMax = 1U << (lengthLog2 + 1); int lengthLog2Bits = lengthLog2 + Bits.Msb(Constants.DigitBitCount); // Create result digits uint[] resultDigits = ArrayPool <uint> .Instance.GetArray(newLengthMax); //new uint[newLengthMax]; uint resultLength; // Create temporary digits for squared result (twice more size) uint[] resultDigitsSqr = ArrayPool <uint> .Instance.GetArray(newLengthMax); //new uint[newLengthMax]; uint resultLengthSqr; // Create temporary digits for squared result * buffer uint[] resultDigitsSqrBuf = new uint[newLengthMax + length]; uint resultLengthSqrBuf; // We will always use current multiplier IMultiplier multiplier = MultiplyManager.GetCurrentMultiplier(); // Fix some digits fixed(uint *resultPtrFixed = resultDigits, resultSqrPtrFixed = resultDigitsSqr, resultSqrBufPtr = resultDigitsSqrBuf) { uint *resultPtr = resultPtrFixed; uint *resultSqrPtr = resultSqrPtrFixed; // Cache two first digits uint bufferDigitN1 = bufferPtr[length - 1]; uint bufferDigitN2 = bufferPtr[length - 2]; // Prepare result. // Initially result = floor(32 / (4*v1 + 2*v2 + v3)) / 4 // (last division is not floored - here we emulate fixed point) resultDigits[0] = 32 / bufferDigitN1; resultLength = 1; // Prepare variables uint nextBufferTempStorage = 0; int nextBufferTempShift; uint nextBufferLength = 1U; uint *nextBufferPtr = &nextBufferTempStorage; ulong bitsAfterDotResult; ulong bitsAfterDotResultSqr; ulong bitsAfterDotNextBuffer; ulong bitShift; uint shiftOffset; uint *tempPtr; uint[] tempDigits; // Iterate 'till result will be precise enough for (int k = 0; k < lengthLog2Bits; ++k) { // Get result squared resultLengthSqr = multiplier.Multiply( resultPtr, resultLength, resultPtr, resultLength, resultSqrPtr); // Calculate current result bits after dot bitsAfterDotResult = (1UL << k) + 1UL; bitsAfterDotResultSqr = bitsAfterDotResult << 1; // Here we will get the next portion of data from bufferPtr if (k < 4) { // For now buffer intermediate has length 1 and we will use this fact nextBufferTempShift = 1 << (k + 1); nextBufferTempStorage = bufferDigitN1 << nextBufferTempShift | bufferDigitN2 >> (Constants.DigitBitCount - nextBufferTempShift); // Calculate amount of bits after dot (simple formula here) bitsAfterDotNextBuffer = (ulong)nextBufferTempShift + 3UL; } else { // Determine length to get from bufferPtr nextBufferLength = System.Math.Min((1U << (k - 4)) + 1U, length); nextBufferPtr = bufferPtr + (length - nextBufferLength); // Calculate amount of bits after dot (simple formula here) bitsAfterDotNextBuffer = (ulong)(nextBufferLength - 1U) * Constants.DigitBitCount + 3UL; } // Multiply result ^ 2 and nextBuffer + calculate new amount of bits after dot resultLengthSqrBuf = multiplier.Multiply( resultSqrPtr, resultLengthSqr, nextBufferPtr, nextBufferLength, resultSqrBufPtr); bitsAfterDotNextBuffer += bitsAfterDotResultSqr; // Now calculate 2 * result - resultSqrBufPtr --bitsAfterDotResult; --bitsAfterDotResultSqr; // Shift result on a needed amount of bits to the left bitShift = bitsAfterDotResultSqr - bitsAfterDotResult; shiftOffset = (uint)(bitShift / Constants.DigitBitCount); resultLength = shiftOffset + 1U + DigitOpHelper.Shr( resultPtr, resultLength, resultSqrPtr + shiftOffset + 1U, Constants.DigitBitCount - (int)(bitShift % Constants.DigitBitCount), true); // Swap resultPtr and resultSqrPtr pointers tempPtr = resultPtr; resultPtr = resultSqrPtr; resultSqrPtr = tempPtr; tempDigits = resultDigits; resultDigits = resultDigitsSqr; resultDigitsSqr = tempDigits; DigitHelper.SetBlockDigits(resultPtr, shiftOffset, 0U); bitShift = bitsAfterDotNextBuffer - bitsAfterDotResultSqr; shiftOffset = (uint)(bitShift / Constants.DigitBitCount); if (shiftOffset < resultLengthSqrBuf) { // Shift resultSqrBufPtr on a needed amount of bits to the right resultLengthSqrBuf = DigitOpHelper.Shr( resultSqrBufPtr + shiftOffset, resultLengthSqrBuf - shiftOffset, resultSqrBufPtr, (int)(bitShift % Constants.DigitBitCount), false); // Now perform actual subtraction resultLength = DigitOpHelper.Sub( resultPtr, resultLength, resultSqrBufPtr, resultLengthSqrBuf, resultPtr); } else { // Actually we can assume resultSqrBufPtr == 0 here and have nothing to do } } } // Return some arrays to pool ArrayPool <uint> .Instance.AddArray(resultDigitsSqr); rightShift += (1UL << lengthLog2Bits) + 1UL; newLength = resultLength; return(resultDigits); }
private static int GetPoolIndexForReuse(int size) { return(Bits.CeilLog2(size) - 1); // x^0 = 1 therefore we start counting at 1 instead. }