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