Msb() public static method

Counts position of the most significant bit in int. Can also be used as Floor(Log2(x)).
public static Msb ( uint x ) : int
x uint Int value.
return int
Exemplo n.º 1
0
 /// <summary>
 /// Converts digits from internal representaion into given base.
 /// </summary>
 /// <param name="digits">Big integer digits.</param>
 /// <param name="length">Big integer length.</param>
 /// <param name="numberBase">Base to use for output.</param>
 /// <param name="outputLength">Calculated output length (will be corrected inside).</param>
 /// <returns>Conversion result (later will be transformed to string).</returns>
 virtual public uint[] ToString(uint[] digits, uint length, uint numberBase, ref uint outputLength)
 {
     // Default implementation - always call pow2 converter if numberBase is pow of 2
     return(numberBase == 1U << Bits.Msb(numberBase)
                         ? _pow2StringConverter.ToString(digits, length, numberBase, ref outputLength)
                         : null);
 }
Exemplo n.º 2
0
 /// <summary>
 /// Parses provided string representation of <see cref="IntX" /> object.
 /// </summary>
 /// <param name="value">Number as string.</param>
 /// <param name="startIndex">Index inside string from which to start.</param>
 /// <param name="endIndex">Index inside string on which to end.</param>
 /// <param name="numberBase">Number base.</param>
 /// <param name="charToDigits">Char->digit dictionary.</param>
 /// <param name="digitsRes">Resulting digits.</param>
 /// <returns>Parsed integer length.</returns>
 virtual public uint Parse(string value, int startIndex, int endIndex, uint numberBase, IDictionary <char, uint> charToDigits, uint[] digitsRes)
 {
     // Default implementation - always call pow2 parser if numberBase is pow of 2
     return(numberBase == 1U << Bits.Msb(numberBase)
                         ? _pow2Parser.Parse(value, startIndex, endIndex, numberBase, charToDigits, digitsRes)
                         : 0);
 }
Exemplo n.º 3
0
        /// <summary>
        /// Parses provided string representation of <see cref="IntX" /> object.
        /// </summary>
        /// <param name="value">Number as string.</param>
        /// <param name="startIndex">Index inside string from which to start.</param>
        /// <param name="endIndex">Index inside string on which to end.</param>
        /// <param name="numberBase">Number base.</param>
        /// <param name="charToDigits">Char->digit dictionary.</param>
        /// <param name="digitsRes">Resulting digits.</param>
        /// <returns>Parsed integer length.</returns>
        public uint Parse(string value, int startIndex, int endIndex, uint numberBase, IDictionary <char, uint> charToDigits, uint[] digitsRes)
        {
            // Calculate length of input string
            int   bitsInChar     = Bits.Msb(numberBase);
            uint  valueLength    = (uint)(endIndex - startIndex + 1);
            ulong valueBitLength = (ulong)valueLength * (ulong)bitsInChar;

            // Calculate needed digits length and first shift
            uint digitsLength = (uint)(valueBitLength / Constants.DigitBitCount) + 1;
            uint digitIndex   = digitsLength - 1;
            int  initialShift = (int)(valueBitLength % Constants.DigitBitCount);

            // Probably correct digits length
            if (initialShift == 0)
            {
                --digitsLength;
            }

            // Do parsing in big cycle
            uint digit;

            for (int i = startIndex; i <= endIndex; ++i)
            {
                digit = StrRepHelper.GetDigit(charToDigits, value[i], numberBase);

                // Correct initial digit shift
                if (initialShift == 0)
                {
                    // If shift is equals to zero then char is not on digit elemtns bounds,
                    // so just go to the previous digit
                    initialShift = Constants.DigitBitCount - bitsInChar;
                    --digitIndex;
                }
                else
                {
                    // Here shift might be negative, but it's okay
                    initialShift -= bitsInChar;
                }

                // Insert new digit in correct place
                digitsRes[digitIndex] |= initialShift < 0 ? digit >> -initialShift : digit << initialShift;

                // In case if shift was negative we also must modify previous digit
                if (initialShift < 0)
                {
                    initialShift            += Constants.DigitBitCount;
                    digitsRes[--digitIndex] |= digit << initialShift;
                }
            }

            if (digitsRes[digitsLength - 1] == 0)
            {
                --digitsLength;
            }
            return(digitsLength);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Returns a specified big integer raised to the specified power.
        /// </summary>
        /// <param name="value">Number to raise.</param>
        /// <param name="power">Power.</param>
        /// <param name="multiplyMode">Multiply mode set explicitly.</param>
        /// <returns>Number in given power.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="value" /> is a null reference.</exception>
        static public IntX Pow(IntX value, uint power, MultiplyMode multiplyMode)
        {
            // Exception
            if (ReferenceEquals(value, null))
            {
                throw new ArgumentNullException("value");
            }

            // Return one for zero pow
            if (power == 0)
            {
                return(1);
            }

            // Return the number itself from a power of one
            if (power == 1)
            {
                return(new IntX(value));
            }

            // Return zero for a zero
            if (value._length == 0)
            {
                return(new IntX());
            }

            // Get first one bit
            int msb = Bits.Msb(power);

            // Get multiplier
            IMultiplier multiplier = MultiplyManager.GetMultiplier(multiplyMode);

            // Do actual raising
            IntX res = value;

            for (uint powerMask = 1U << (msb - 1); powerMask != 0; powerMask >>= 1)
            {
                // Always square
                res = multiplier.Multiply(res, res);

                // Maybe mul
                if ((power & powerMask) != 0)
                {
                    res = multiplier.Multiply(res, value);
                }
            }
            return(res);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Either returns array of given size from pool or creates it.
        /// </summary>
        /// <param name="length">Array length (always pow of 2).</param>
        /// <returns>Always array instance ready to use.</returns>
        public T[] GetArray(uint length)
        {
            int lengthLog2 = Bits.Msb(length);

            // Check if we can search in pool
            if (lengthLog2 >= _minPooledArraySizeLog2 && lengthLog2 <= _maxPooledArraySizeLog2)
            {
                // Get needed pool
                Stack <WeakReference> pool = _pools[lengthLog2 - _minPooledArraySizeLog2];

                // Try to find at least one not collected array of given size
                while (pool.Count > 0)
                {
                    WeakReference arrayRef;
                    lock (pool)
                    {
                        // Double-guard here
                        if (pool.Count > 0)
                        {
                            arrayRef = pool.Pop();
                        }
                        else
                        {
                            // Well, we can exit here
                            break;
                        }
                    }

                    // Maybe return found array if link is alive
                    T[] array = (T[])arrayRef.Target;
                    if (arrayRef.IsAlive)
                    {
                        return(array);
                    }
                }
            }

            // Array can't be found in pool - create new one
            return(new T[length]);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Adds array to pool.
        /// </summary>
        /// <param name="array">Array to add (it/s length is always pow of 2).</param>
        public void AddArray(T[] array)
        {
            int lengthLog2 = Bits.Msb((uint)array.LongLength);

            // Check if we can add in pool
            if (lengthLog2 >= _minPooledArraySizeLog2 && lengthLog2 <= _maxPooledArraySizeLog2)
            {
                // Get needed pool
                Stack <WeakReference> pool = _pools[lengthLog2 - _minPooledArraySizeLog2];

                // Add array to pool (only if pool size is not too big)
                if (pool.Count <= _maxPoolCount)
                {
                    lock (pool)
                    {
                        // Double-guard here
                        if (pool.Count <= _maxPoolCount)
                        {
                            pool.Push(new WeakReference(array));
                        }
                    }
                }
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Shifts <see cref="IntX" /> object.
        /// Determines which operation to use basing on shift sign.
        /// </summary>
        /// <param name="intX">Big integer.</param>
        /// <param name="shift">Bits count to shift.</param>
        /// <param name="toLeft">If true the shifting to the left.</param>
        /// <returns>Bitwise shift operation result.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="intX" /> is a null reference.</exception>
        static public IntX Sh(IntX intX, long shift, bool toLeft)
        {
            // Exceptions
            if (ReferenceEquals(intX, null))
            {
                throw new ArgumentNullException("intX", Strings.CantBeNullOne);
            }

            // Zero can't be shifted
            if (intX._length == 0)
            {
                return(new IntX());
            }

            // Can't shift on zero value
            if (shift == 0)
            {
                return(new IntX(intX));
            }

            // Determine real bits count and direction
            ulong bitCount;
            bool  negativeShift;

            DigitHelper.ToUInt64WithSign(shift, out bitCount, out negativeShift);
            toLeft ^= negativeShift;

            // Get position of the most significant bit in intX and amount of bits in intX
            int   msb          = Bits.Msb(intX._digits[intX._length - 1]);
            ulong intXBitCount = (ulong)(intX._length - 1) * Constants.DigitBitCount + (ulong)msb + 1UL;

            // If shifting to the right and shift is too big then return zero
            if (!toLeft && bitCount >= intXBitCount)
            {
                return(new IntX());
            }

            // Calculate new bit count
            ulong newBitCount = toLeft ? intXBitCount + bitCount : intXBitCount - bitCount;

            // If shifting to the left and shift is too big to fit in big integer, throw an exception
            if (toLeft && newBitCount > Constants.MaxBitCount)
            {
                throw new ArgumentException(Strings.IntegerTooBig, "intX");
            }

            // Get exact length of new big integer (no normalize is ever needed here).
            // Create new big integer with given length
            uint newLength = (uint)(newBitCount / Constants.DigitBitCount + (newBitCount % Constants.DigitBitCount == 0 ? 0UL : 1UL));
            IntX newInt    = new IntX(newLength, intX._negative);

            // Get full and small shift values
            uint fullDigits = (uint)(bitCount / Constants.DigitBitCount);
            int  smallShift = (int)(bitCount % Constants.DigitBitCount);

            // We can just copy (no shift) if small shift is zero
            if (smallShift == 0)
            {
                if (toLeft)
                {
                    Array.Copy(intX._digits, 0, newInt._digits, fullDigits, intX._length);
                }
                else
                {
                    Array.Copy(intX._digits, fullDigits, newInt._digits, 0, newLength);
                }
            }
            else
            {
                // Do copy with real shift in the needed direction
                if (toLeft)
                {
                    DigitOpHelper.Shr(intX._digits, 0, intX._length, newInt._digits, fullDigits + 1, Constants.DigitBitCount - smallShift);
                }
                else
                {
                    // If new result length is smaller then original length we shouldn't lose any digits
                    if (newLength < (intX._length - fullDigits))
                    {
                        newLength++;
                    }

                    DigitOpHelper.Shr(intX._digits, fullDigits, newLength, newInt._digits, 0, smallShift);
                }
            }

            return(newInt);
        }