private uint NextUInt32(uint maxValue)
        {
            if (maxValue == 0)
            {
                return(0);
            }
            // determine the position of MSB
            uint mask;

            if (maxValue == this.cachedMaxValue)
            {
                mask = this.cachedValueMask;
            }
            else
            {
                this.cachedMaxValue = maxValue;
                mask = this.cachedValueMask = BitScanner.Mask(maxValue - 1);
            }
            //
            uint num;

            do
            {
                num  = this.NextUInt32();
                num &= mask;
            } while (num >= maxValue);
            return(num);
        }
        private static double FullPrecisionDouble_c0o1(Random rng, byte[] buffer)
        {
            const int EffectiveBits = BUFFER_SIZE * 8;
            // exponent
            var e = -1;

            do
            {
                rng.NextBytes(buffer);
                var r   = BitConverter.ToUInt64(buffer, 0);
                var ntz = BitScanner.NumberOfTrailingZeros64(r);
                if (ntz < EffectiveBits)
                {
                    e -= ntz;
                    break;
                }
                e -= EffectiveBits;
            } while (e > -1024);
            //
            if (e <= -1024)
            {
                return(0);
            }
            // fraction
            rng.NextBytes(buffer);
            var f = (long)(BitConverter.ToUInt64(buffer, 0) >> 12);

            // IEEE-754
            return(BitConverter.Int64BitsToDouble(((long)(e + 1023) << 52) | f));
        }