Пример #1
0
        public void CountLeadinZeros()
        {
            Random r = new Random();

            Assert.AreEqual(32, BitMath.CountLeadingZeros(0u));
            Assert.AreEqual(0, BitMath.CountLeadingZeros(uint.MaxValue));

            for (int k = 0; k < 10; k++)
            {
                for (int x = 0; x < 32; x++)
                {
                    Assert.AreEqual(31 - x, BitMath.CountLeadingZeros(1u << x | Next(r, 1u << x)));
                }
            }

            Assert.AreEqual(64, BitMath.CountLeadingZeros(0ul));
            Assert.AreEqual(0, BitMath.CountLeadingZeros(ulong.MaxValue));

            for (int k = 0; k < 10; k++)
            {
                for (int x = 0; x < 63; x++)
                {
                    Assert.AreEqual(63 - x, BitMath.CountLeadingZeros(1ul << x | Next(r, 1ul << x)));
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Returns a cryptographically strong number that is less than the the supplied value
        /// </summary>
        /// <param name="maxValue">the max value to return exclusive</param>
        /// <returns></returns>
        /// <remarks>
        /// if 0 is provided, 0 is returned
        /// </remarks>
        private static ulong GetRandomNumberLessThan(ulong maxValue)
        {
            //A crypto number cannot be achieved via *, /, or % since these
            //operations have rounding and uneven redistribution properties.

            //Method: In order to get a crypto number <= maxValue
            //A random number must be generated. If the random number is in range, it
            //may be kept, otherwise a new number must be generated.
            //To increase the likelihood that the number is in range,
            //bit masking can be used on the higher order bits to
            //create a 75% likelihood (on average) that the number will be in range.

            //Exception cases where algorithm doesn't work
            if (maxValue == 0 || maxValue == 1)
            {
                return(0);
            }

            //Determine the number of random bits that I need
            int leadingZeroes = BitMath.CountLeadingZeros(maxValue);

            ulong value = UInt64;

            //By shifting the value by the number of leading zeros, I'll have
            //a number with the highest likelihood of being in range
            while (value >> leadingZeroes >= maxValue)
            {
                //If the number is outside of range, all bits must
                //be discarded and new ones generated. Not doing this
                //technically alters the crypto-random nature of the value being generated.
                value = UInt64;
            }
            return(value >> leadingZeroes);
        }
Пример #3
0
        public void BitMath_Should_Return_Count_Of_31()
        {
            //Integer as 32 digit binary number
            Int32       actual   = BitMath.CountLeadingZeros(1);
            const Int32 expected = 31;

            Assert.Equal(expected, actual);
        }
Пример #4
0
        public void BitMath_Should_Return_Count_Of_28()
        {
            //Integer as 32 digit binary number
            //15 = 1111 in binary, so 32 - 4 = 28
            Int32       actual   = BitMath.CountLeadingZeros(15);
            const Int32 expected = 28;

            Assert.Equal(expected, actual);
        }
Пример #5
0
        /// <summary>
        /// Defines a binary-to-text encoding.
        /// Additional decode characters let you add aliases, and a filter callback can be used
        /// to make decoding case-insensitive among other things.
        /// </summary>
        /// <param name="characterSet">The characters of the encoding.</param>
        /// <param name="msbComesFirst">
        ///     <c>true</c> to begin with the most-significant bit of each byte.
        ///     Otherwise, the encoding begins with the least-significant bit.
        /// </param>
        /// <param name="additionalDecodeCharacters">
        ///     A dictionary of alias characters, or <c>null</c> if no aliases are desired.
        /// </param>
        /// <param name="decodeFilterCallback">
        ///     A callback to map arbitrary characters onto the characters that can be decoded.
        /// </param>
        public BaseEncoding(string characterSet, bool msbComesFirst,
                            IDictionary <char, int> additionalDecodeCharacters,
                            BaseEncodingDecodeFilterCallback decodeFilterCallback)
        {
            Check.Null("characterSet", characterSet);

            if (!BitMath.IsPositivePowerOf2(characterSet.Length))
            {
                throw Exceptions.Argument("characterSet",
                                          "Length must be a power of 2.");
            }

            if (characterSet.Length > 256)
            {
                throw Exceptions.Argument("characterSet",
                                          "Character sets with over 256 characters are not supported.");
            }

            _bitCount             = 31 - BitMath.CountLeadingZeros(characterSet.Length);
            _bitMask              = (1 << _bitCount) - 1;
            _characters           = characterSet;
            _msbComesFirst        = msbComesFirst;
            _decodeFilterCallback = decodeFilterCallback;

            _values = additionalDecodeCharacters != null
                ? new Dictionary <char, int>(additionalDecodeCharacters)
                : new Dictionary <char, int>();
            for (int i = 0; i < characterSet.Length; i++)
            {
                char ch = characterSet[i];
                if (_values.ContainsKey(ch))
                {
                    throw Exceptions.Argument("Duplicate characters are not supported.",
                                              "characterSet");
                }
                _values.Add(ch, (byte)i);
            }
        }