Exemple #1
0
        /// <summary>
        /// Try parsing a correctly-formatted float floating-point literal into the nearest representable float
        /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are
        /// not valid C# floating-point literals.
        /// </summary>
        /// <param name="s">The float floating-point constant's string</param>
        /// <param name="f">The nearest float value, if conversion succeeds</param>
        /// <returns>True if the input was converted; false if there was an overflow</returns>
        public static bool TryParseFloat(string s, out float f)
        {
            DecimalFloatingPointString str = DecimalFloatingPointString.FromSource(s);
            FloatFloatingPointType     dbl = FloatFloatingPointType.Instance;
            Status status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out ulong result);

            f = Int32BitsToFloat((uint)result);
            return(status != Status.Overflow);
        }
Exemple #2
0
        /// <summary>
        /// Try parsing a correctly-formatted double floating-point literal into the nearest representable double
        /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are
        /// not valid C# floating-point literals.
        /// </summary>
        /// <param name="s">The decimal floating-point constant's string</param>
        /// <param name="d">The nearest double value, if conversion succeeds</param>
        /// <returns>True if the input was converted; false if there was an overflow</returns>
        public static bool TryParseDouble(string s, out double d)
        {
            DecimalFloatingPointString str = DecimalFloatingPointString.FromSource(s);
            DoubleFloatingPointType    dbl = DoubleFloatingPointType.Instance;
            Status status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out ulong result);

            d = BitConverter.Int64BitsToDouble((long)result);
            return(status != Status.Overflow);
        }
Exemple #3
0
        /// <summary>
        /// Try parsing a correctly-formatted float floating-point literal into the nearest representable float
        /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are
        /// not valid C# floating-point literals.
        /// </summary>
        /// <param name="s">The float floating-point constant's string</param>
        /// <param name="f">The nearest float value, if conversion succeeds</param>
        /// <returns>True if the input was converted; false if there was an overflow</returns>
        public static bool TryParseFloat(string s, out float f)
        {
            var str    = DecimalFloatingPointString.FromSource(s);
            var dbl    = FloatFloatingPointType.Instance;
            var status = ConvertDecimalToFloatingPointBits(str, dbl, out var result);

            f = Int32BitsToFloat((uint)result);
            return(status != Status.Overflow);
        }
Exemple #4
0
        /// <summary>
        /// Parse a sequence of digits into a BigInteger.
        /// </summary>
        /// <param name="data">The DecimalFloatingPointString containing the digits in its Mantissa</param>
        /// <param name="integer_first_index">The index of the first digit to convert</param>
        /// <param name="integer_last_index">The index just past the last digit to convert</param>
        /// <returns>The BigInteger result</returns>
        private static BigInteger AccumulateDecimalDigitsIntoBigInteger(DecimalFloatingPointString data, uint integer_first_index, uint integer_last_index)
        {
            if (integer_first_index == integer_last_index)
            {
                return(BigZero);
            }
            var valueString = data.Mantissa.Substring((int)integer_first_index, (int)(integer_last_index - integer_first_index));

            return(BigInteger.Parse(valueString.TrimStart('0'))); // our bigint does octals too
        }
Exemple #5
0
        /// <summary>
        /// Try parsing a correctly-formatted float floating-point literal into the nearest representable float
        /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are
        /// not valid C# floating-point literals.
        /// </summary>
        /// <param name="s">The float floating-point constant's string</param>
        /// <param name="f">The nearest float value, if conversion succeeds</param>
        /// <returns>True of the input was converted; false if there was an overflow</returns>
        public static bool TryParseFloat(string s, out float f)
        {
            var   str = DecimalFloatingPointString.FromSource(s);
            var   dbl = FloatFloatingPointType.Instance;
            ulong result;
            var   status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out result);

            f = Int32BitsToFloat((uint)result);
            return(status != SLD_STATUS.SLD_OVERFLOW);
        }
Exemple #6
0
        /// <summary>
        /// Try parsing a correctly-formatted double floating-point literal into the nearest representable double
        /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are
        /// not valid C# floating-point literals.
        /// </summary>
        /// <param name="s">The decimal floating-point constant's string</param>
        /// <param name="d">The nearest double value, if conversion succeeds</param>
        /// <returns>True of the input was converted; false if there was an overflow</returns>
        public static bool TryParseDouble(string s, out double d)
        {
            var   str = DecimalFloatingPointString.FromSource(s);
            var   dbl = DoubleFloatingPointType.Instance;
            ulong result;
            var   status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out result);

            d = BitConverter.Int64BitsToDouble((long)result);
            return(status != SLD_STATUS.SLD_OVERFLOW);
        }
Exemple #7
0
        /// <summary>
        /// Parse a sequence of digits into a BigInteger.
        /// </summary>
        /// <param name="data">The DecimalFloatingPointString containing the digits in its Mantissa</param>
        /// <param name="integer_first_index">The index of the first digit to convert</param>
        /// <param name="integer_last_index">The index just past the last digit to convert</param>
        /// <returns>The BigInteger result</returns>
        private static BigInteger AccumulateDecimalDigitsIntoBigInteger(DecimalFloatingPointString data, uint integer_first_index, uint integer_last_index)
        {
            if (integer_first_index == integer_last_index)
            {
                return(s_bigZero);
            }
            var valueString = data.Mantissa.Substring((int)integer_first_index, (int)(integer_last_index - integer_first_index));

            return(BigInteger.Parse(valueString));
        }
Exemple #8
0
 /// <summary>
 /// Try parsing a correctly-formatted float floating-point literal into the nearest representable float
 /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are
 /// not valid C# floating-point literals.
 /// </summary>
 /// <param name="s">The float floating-point constant's string</param>
 /// <param name="f">The nearest float value, if conversion succeeds</param>
 /// <returns>True of the input was converted; false if there was an overflow</returns>
 public static bool TryParseFloat(string s, out float f)
 {
     try
     {
         var   str = DecimalFloatingPointString.FromSource(s);
         var   dbl = FloatFloatingPointType.Instance;
         ulong result;
         var   status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out result);
         f = Int32BitsToFloat((uint)result);
         return(status != Status.Overflow);
     }
     catch (System.FormatException)
     {
         f = 0.0f;
         return(false);
     }
 }
Exemple #9
0
 /// <summary>
 /// Try parsing a correctly-formatted double floating-point literal into the nearest representable double
 /// using IEEE round-to-nearest-ties-to-even rounding mode. Behavior is not defined for inputs that are
 /// not valid C# floating-point literals.
 /// </summary>
 /// <param name="s">The decimal floating-point constant's string</param>
 /// <param name="d">The nearest double value, if conversion succeeds</param>
 /// <returns>True of the input was converted; false if there was an overflow</returns>
 public static bool TryParseDouble(string s, out double d)
 {
     try
     {
         var   str = DecimalFloatingPointString.FromSource(s);
         var   dbl = DoubleFloatingPointType.Instance;
         ulong result;
         var   status = RealParser.ConvertDecimalToFloatingPointBits(str, dbl, out result);
         d = BitConverter.Int64BitsToDouble((long)result);
         return(status != Status.Overflow);
     }
     catch (System.FormatException)
     {
         // this can occur when the exponent is empty (e.g. "0.0e") or too large to fit in an integer
         d = 0.0;
         return(false);
     }
 }
Exemple #10
0
        /// <summary>
        /// Convert a DecimalFloatingPointString to the bits of the given floating-point type.
        /// </summary>
        private static SLD_STATUS ConvertDecimalToFloatingPointBits(DecimalFloatingPointString data, FloatingPointType type, out ulong result)
        {
            if (data.Mantissa.Length == 0)
            {
                result = type.Zero;
                return(SLD_STATUS.SLD_NODIGITS);
            }

            // To generate an N bit mantissa we require N + 1 bits of precision.  The
            // extra bit is used to correctly round the mantissa (if there are fewer bits
            // than this available, then that's totally okay; in that case we use what we
            // have and we don't need to round).
            uint requiredBitsOfPrecision = (uint)type.NormalMantissaBits + 1;

            // The input is of the form 0.Mantissa x 10^Exponent, where 'Mantissa' are
            // the decimal digits of the mantissa and 'Exponent' is the decimal exponent.
            // We decompose the mantissa into two parts: an integer part and a fractional
            // part.  If the exponent is positive, then the integer part consists of the
            // first 'exponent' digits, or all present digits if there are fewer digits.
            // If the exponent is zero or negative, then the integer part is empty.  In
            // either case, the remaining digits form the fractional part of the mantissa.
            uint positiveExponent     = (uint)Math.Max(0, data.Exponent);
            uint integerDigitsPresent = Math.Min(positiveExponent, data.MantissaCount);
            uint integerDigitsMissing = positiveExponent - integerDigitsPresent;
            uint integerFirstIndex    = 0;
            uint integerLastIndex     = integerDigitsPresent;

            uint fractionalFirstIndex    = integerLastIndex;
            uint fractionalLastIndex     = data.MantissaCount;
            uint fractionalDigitsPresent = fractionalLastIndex - fractionalFirstIndex;

            // First, we accumulate the integer part of the mantissa into a big_integer:
            BigInteger integerValue = AccumulateDecimalDigitsIntoBigInteger(data, integerFirstIndex, integerLastIndex);

            if (integerDigitsMissing > 0)
            {
                if (integerDigitsMissing > type.OverflowDecimalExponent)
                {
                    result = type.Infinity;
                    return(SLD_STATUS.SLD_OVERFLOW);
                }

                MultiplyByPowerOfTen(ref integerValue, integerDigitsMissing);
            }

            // At this point, the integer_value contains the value of the integer part
            // of the mantissa.  If either [1] this number has more than the required
            // number of bits of precision or [2] the mantissa has no fractional part,
            // then we can assemble the result immediately:
            byte[] integerValueAsBytes;
            uint   integerBitsOfPrecision = CountSignificantBits(integerValue, out integerValueAsBytes);

            if (integerBitsOfPrecision >= requiredBitsOfPrecision ||
                fractionalDigitsPresent == 0)
            {
                return(ConvertBigIntegerToFloatingPointBits(
                           integerValueAsBytes,
                           integerBitsOfPrecision,
                           fractionalDigitsPresent != 0,
                           type,
                           out result));
            }

            // Otherwise, we did not get enough bits of precision from the integer part,
            // and the mantissa has a fractional part.  We parse the fractional part of
            // the mantsisa to obtain more bits of precision.  To do this, we convert
            // the fractional part into an actual fraction N/M, where the numerator N is
            // computed from the digits of the fractional part, and the denominator M is
            // computed as the power of 10 such that N/M is equal to the value of the
            // fractional part of the mantissa.

            uint fractionalDenominatorExponent = data.Exponent < 0
                ? fractionalDigitsPresent + (uint)-data.Exponent
                : fractionalDigitsPresent;

            if (integerBitsOfPrecision == 0 && (fractionalDenominatorExponent - (int)data.MantissaCount) > type.OverflowDecimalExponent)
            {
                // If there were any digits in the integer part, it is impossible to
                // underflow (because the exponent cannot possibly be small enough),
                // so if we underflow here it is a true underflow and we return zero.
                result = type.Zero;
                return(SLD_STATUS.SLD_UNDERFLOW);
            }

            BigInteger fractionalNumerator = AccumulateDecimalDigitsIntoBigInteger(data, fractionalFirstIndex, fractionalLastIndex);
            //Debug.Assert(!fractionalNumerator.IsZero);

            BigInteger fractionalDenominator = BigOne;

            MultiplyByPowerOfTen(ref fractionalDenominator, fractionalDenominatorExponent);

            // Because we are using only the fractional part of the mantissa here, the
            // numerator is guaranteed to be smaller than the denominator.  We normalize
            // the fraction such that the most significant bit of the numerator is in
            // the same position as the most significant bit in the denominator.  This
            // ensures that when we later shift the numerator N bits to the left, we
            // will produce N bits of precision.
            uint fractionalNumeratorBits   = CountSignificantBits(fractionalNumerator);
            uint fractionalDenominatorBits = CountSignificantBits(fractionalDenominator);

            uint fractionalShift = fractionalDenominatorBits > fractionalNumeratorBits
                ? fractionalDenominatorBits - fractionalNumeratorBits
                : 0;

            if (fractionalShift > 0)
            {
                ShiftLeft(ref fractionalNumerator, fractionalShift);
            }

            uint requiredFractionalBitsOfPrecision =
                requiredBitsOfPrecision -
                integerBitsOfPrecision;

            uint remainingBitsOfPrecisionRequired = requiredFractionalBitsOfPrecision;

            if (integerBitsOfPrecision > 0)
            {
                // If the fractional part of the mantissa provides no bits of precision
                // and cannot affect rounding, we can just take whatever bits we got from
                // the integer part of the mantissa.  This is the case for numbers like
                // 5.0000000000000000000001, where the significant digits of the fractional
                // part start so far to the right that they do not affect the floating
                // point representation.
                //
                // If the fractional shift is exactly equal to the number of bits of
                // precision that we require, then no fractional bits will be part of the
                // result, but the result may affect rounding.  This is e.g. the case for
                // large, odd integers with a fractional part greater than or equal to .5.
                // Thus, we need to do the division to correctly round the result.
                if (fractionalShift > remainingBitsOfPrecisionRequired)
                {
                    return(ConvertBigIntegerToFloatingPointBits(
                               integerValueAsBytes,
                               integerBitsOfPrecision,
                               fractionalDigitsPresent != 0,
                               type,
                               out result));
                }

                remainingBitsOfPrecisionRequired -= fractionalShift;
            }

            // If there was no integer part of the mantissa, we will need to compute the
            // exponent from the fractional part.  The fractional exponent is the power
            // of two by which we must multiply the fractional part to move it into the
            // range [1.0, 2.0).  This will either be the same as the shift we computed
            // earlier, or one greater than that shift:
            uint fractionalExponent = fractionalNumerator < fractionalDenominator
                ? fractionalShift + 1
                : fractionalShift;

            ShiftLeft(ref fractionalNumerator, remainingBitsOfPrecisionRequired);
            BigInteger fractionalRemainder;
            BigInteger bigFractionalMantissa = BigInteger.DivideModulo(fractionalNumerator, fractionalDenominator, out fractionalRemainder);
            ulong      fractionalMantissa    = (ulong)bigFractionalMantissa;

            bool hasZeroTail = fractionalRemainder == BigZero;

            // We may have produced more bits of precision than were required.  Check,
            // and remove any "extra" bits:
            uint fractionalMantissaBits = CountSignificantBits(fractionalMantissa);

            if (fractionalMantissaBits > requiredFractionalBitsOfPrecision)
            {
                int shift = (int)(fractionalMantissaBits - requiredFractionalBitsOfPrecision);
                hasZeroTail          = hasZeroTail && (fractionalMantissa & ((1UL << shift) - 1)) == 0;
                fractionalMantissa >>= shift;
            }

            // Compose the mantissa from the integer and fractional parts:
            Debug.Assert(integerBitsOfPrecision < 60); // we can use BigInteger's built-in conversion
            ulong integerMantissa = (ulong)integerValue;

            ulong completeMantissa =
                (integerMantissa << (int)requiredFractionalBitsOfPrecision) +
                fractionalMantissa;

            // Compute the final exponent:
            // * If the mantissa had an integer part, then the exponent is one less than
            //   the number of bits we obtained from the integer part.  (It's one less
            //   because we are converting to the form 1.11111, with one 1 to the left
            //   of the decimal point.)
            // * If the mantissa had no integer part, then the exponent is the fractional
            //   exponent that we computed.
            // Then, in both cases, we subtract an additional one from the exponent, to
            // account for the fact that we've generated an extra bit of precision, for
            // use in rounding.
            int finalExponent = integerBitsOfPrecision > 0
                ? (int)integerBitsOfPrecision - 2
                : -(int)(fractionalExponent) - 1;

            return(type.AssembleFloatingPointValue(completeMantissa, finalExponent, hasZeroTail, out result));
        }
Exemple #11
0
 /// <summary>
 /// Parse a sequence of digits into a BigInteger.
 /// </summary>
 /// <param name="data">The DecimalFloatingPointString containing the digits in its Mantissa</param>
 /// <param name="integer_first_index">The index of the first digit to convert</param>
 /// <param name="integer_last_index">The index just past the last digit to convert</param>
 /// <returns>The BigInteger result</returns>
 private static BigInteger AccumulateDecimalDigitsIntoBigInteger(DecimalFloatingPointString data, uint integer_first_index, uint integer_last_index)
 {
     if (integer_first_index == integer_last_index) return BigZero;
     var valueString = data.Mantissa.Substring((int)integer_first_index, (int)(integer_last_index - integer_first_index));
     return BigInteger.Parse(valueString);
 }
Exemple #12
0
        /// <summary>
        /// Convert a DecimalFloatingPointString to the bits of the given floating-point type.
        /// </summary>
        private static Status ConvertDecimalToFloatingPointBits(DecimalFloatingPointString data, FloatingPointType type, out ulong result)
        {
            if (data.Mantissa.Length == 0)
            {
                result = type.Zero;
                return Status.NoDigits;
            }

            // To generate an N bit mantissa we require N + 1 bits of precision.  The  
            // extra bit is used to correctly round the mantissa (if there are fewer bits  
            // than this available, then that's totally okay; in that case we use what we  
            // have and we don't need to round).
            uint requiredBitsOfPrecision = (uint)type.NormalMantissaBits + 1;

            // The input is of the form 0.Mantissa x 10^Exponent, where 'Mantissa' are  
            // the decimal digits of the mantissa and 'Exponent' is the decimal exponent.  
            // We decompose the mantissa into two parts: an integer part and a fractional  
            // part.  If the exponent is positive, then the integer part consists of the  
            // first 'exponent' digits, or all present digits if there are fewer digits.  
            // If the exponent is zero or negative, then the integer part is empty.  In  
            // either case, the remaining digits form the fractional part of the mantissa.  
            uint positiveExponent = (uint)Math.Max(0, data.Exponent);
            uint integerDigitsPresent = Math.Min(positiveExponent, data.MantissaCount);
            uint integerDigitsMissing = positiveExponent - integerDigitsPresent;
            uint integerFirstIndex = 0;
            uint integerLastIndex = integerDigitsPresent;

            uint fractionalFirstIndex = integerLastIndex;
            uint fractionalLastIndex = data.MantissaCount;
            uint fractionalDigitsPresent = fractionalLastIndex - fractionalFirstIndex;

            // First, we accumulate the integer part of the mantissa into a big_integer:
            BigInteger integerValue = AccumulateDecimalDigitsIntoBigInteger(data, integerFirstIndex, integerLastIndex);

            if (integerDigitsMissing > 0)
            {
                if (integerDigitsMissing > type.OverflowDecimalExponent)
                {
                    result = type.Infinity;
                    return Status.Overflow;
                }

                MultiplyByPowerOfTen(ref integerValue, integerDigitsMissing);
            }

            // At this point, the integer_value contains the value of the integer part
            // of the mantissa.  If either [1] this number has more than the required
            // number of bits of precision or [2] the mantissa has no fractional part,
            // then we can assemble the result immediately:
            byte[] integerValueAsBytes;
            uint integerBitsOfPrecision = CountSignificantBits(integerValue, out integerValueAsBytes);
            if (integerBitsOfPrecision >= requiredBitsOfPrecision ||
                fractionalDigitsPresent == 0)
            {
                return ConvertBigIntegerToFloatingPointBits(
                    integerValueAsBytes,
                    integerBitsOfPrecision,
                    fractionalDigitsPresent != 0,
                    type,
                    out result);
            }

            // Otherwise, we did not get enough bits of precision from the integer part,  
            // and the mantissa has a fractional part.  We parse the fractional part of  
            // the mantsisa to obtain more bits of precision.  To do this, we convert  
            // the fractional part into an actual fraction N/M, where the numerator N is  
            // computed from the digits of the fractional part, and the denominator M is   
            // computed as the power of 10 such that N/M is equal to the value of the  
            // fractional part of the mantissa.  

            uint fractionalDenominatorExponent = data.Exponent < 0
                ? fractionalDigitsPresent + (uint)-data.Exponent
                : fractionalDigitsPresent;
            if (integerBitsOfPrecision == 0 && (fractionalDenominatorExponent - (int)data.MantissaCount) > type.OverflowDecimalExponent)
            {
                // If there were any digits in the integer part, it is impossible to  
                // underflow (because the exponent cannot possibly be small enough),  
                // so if we underflow here it is a true underflow and we return zero.  
                result = type.Zero;
                return Status.Undeflow;
            }

            BigInteger fractionalNumerator = AccumulateDecimalDigitsIntoBigInteger(data, fractionalFirstIndex, fractionalLastIndex);
            Debug.Assert(!fractionalNumerator.IsZero);

            BigInteger fractionalDenominator = BigOne;
            MultiplyByPowerOfTen(ref fractionalDenominator, fractionalDenominatorExponent);

            // Because we are using only the fractional part of the mantissa here, the  
            // numerator is guaranteed to be smaller than the denominator.  We normalize  
            // the fraction such that the most significant bit of the numerator is in  
            // the same position as the most significant bit in the denominator.  This  
            // ensures that when we later shift the numerator N bits to the left, we  
            // will produce N bits of precision.  
            uint fractionalNumeratorBits = CountSignificantBits(fractionalNumerator);
            uint fractionalDenominatorBits = CountSignificantBits(fractionalDenominator);

            uint fractionalShift = fractionalDenominatorBits > fractionalNumeratorBits
                ? fractionalDenominatorBits - fractionalNumeratorBits
                : 0;

            if (fractionalShift > 0)
            {
                ShiftLeft(ref fractionalNumerator, fractionalShift);
            }

            uint requiredFractionalBitsOfPrecision =
                requiredBitsOfPrecision -
                integerBitsOfPrecision;

            uint remainingBitsOfPrecisionRequired = requiredFractionalBitsOfPrecision;
            if (integerBitsOfPrecision > 0)
            {
                // If the fractional part of the mantissa provides no bits of precision  
                // and cannot affect rounding, we can just take whatever bits we got from  
                // the integer part of the mantissa.  This is the case for numbers like  
                // 5.0000000000000000000001, where the significant digits of the fractional  
                // part start so far to the right that they do not affect the floating  
                // point representation.  
                //  
                // If the fractional shift is exactly equal to the number of bits of  
                // precision that we require, then no fractional bits will be part of the  
                // result, but the result may affect rounding.  This is e.g. the case for  
                // large, odd integers with a fractional part greater than or equal to .5.  
                // Thus, we need to do the division to correctly round the result.  
                if (fractionalShift > remainingBitsOfPrecisionRequired)
                {
                    return ConvertBigIntegerToFloatingPointBits(
                        integerValueAsBytes,
                        integerBitsOfPrecision,
                        fractionalDigitsPresent != 0,
                        type,
                        out result);
                }

                remainingBitsOfPrecisionRequired -= fractionalShift;
            }

            // If there was no integer part of the mantissa, we will need to compute the  
            // exponent from the fractional part.  The fractional exponent is the power  
            // of two by which we must multiply the fractional part to move it into the  
            // range [1.0, 2.0).  This will either be the same as the shift we computed  
            // earlier, or one greater than that shift:  
            uint fractionalExponent = fractionalNumerator < fractionalDenominator
                ? fractionalShift + 1
                : fractionalShift;

            ShiftLeft(ref fractionalNumerator, remainingBitsOfPrecisionRequired);
            BigInteger fractionalRemainder;
            BigInteger bigFractionalMantissa = BigInteger.DivRem(fractionalNumerator, fractionalDenominator, out fractionalRemainder);
            ulong fractionalMantissa = (ulong)bigFractionalMantissa;

            bool hasZeroTail = fractionalRemainder.IsZero;

            // We may have produced more bits of precision than were required.  Check,  
            // and remove any "extra" bits:  
            uint fractionalMantissaBits = CountSignificantBits(fractionalMantissa);
            if (fractionalMantissaBits > requiredFractionalBitsOfPrecision)
            {
                int shift = (int)(fractionalMantissaBits - requiredFractionalBitsOfPrecision);
                hasZeroTail = hasZeroTail && (fractionalMantissa & ((1UL << shift) - 1)) == 0;
                fractionalMantissa >>= shift;
            }

            // Compose the mantissa from the integer and fractional parts:  
            Debug.Assert(integerBitsOfPrecision < 60); // we can use BigInteger's built-in conversion
            ulong integerMantissa = (ulong)integerValue;

            ulong completeMantissa =
                (integerMantissa << (int)requiredFractionalBitsOfPrecision) +
                fractionalMantissa;

            // Compute the final exponent:  
            // * If the mantissa had an integer part, then the exponent is one less than  
            //   the number of bits we obtained from the integer part.  (It's one less  
            //   because we are converting to the form 1.11111, with one 1 to the left  
            //   of the decimal point.)  
            // * If the mantissa had no integer part, then the exponent is the fractional  
            //   exponent that we computed.  
            // Then, in both cases, we subtract an additional one from the exponent, to  
            // account for the fact that we've generated an extra bit of precision, for  
            // use in rounding.  
            int finalExponent = integerBitsOfPrecision > 0
                ? (int)integerBitsOfPrecision - 2
                : -(int)(fractionalExponent) - 1;

            return type.AssembleFloatingPointValue(completeMantissa, finalExponent, hasZeroTail, out result);
        }
Exemple #13
0
            /// <summary>
            /// Create a DecimalFloatingPointString from a string representing a floating-point literal.
            /// </summary>
            /// <param name="source">The text of the floating-point literal</param>
            public static DecimalFloatingPointString FromSource(string source)
            {
                StringBuilder mantissaBuilder = new StringBuilder();
                int           exponent        = 0;
                int           i = 0;

                while (i < source.Length && source[i] == '0')
                {
                    i++;
                }
                int skippedDecimals = 0;

                while (i < source.Length && source[i] >= '0' && source[i] <= '9')
                {
                    if (source[i] == '0')
                    {
                        skippedDecimals++;
                    }
                    else
                    {
                        mantissaBuilder.Append('0', skippedDecimals);
                        skippedDecimals = 0;
                        mantissaBuilder.Append(source[i]);
                    }
                    exponent++;
                    i++;
                }
                if (i < source.Length && source[i] == '.')
                {
                    i++;
                    while (i < source.Length && source[i] >= '0' && source[i] <= '9')
                    {
                        if (source[i] == '0')
                        {
                            skippedDecimals++;
                        }
                        else
                        {
                            mantissaBuilder.Append('0', skippedDecimals);
                            skippedDecimals = 0;
                            mantissaBuilder.Append(source[i]);
                        }
                        i++;
                    }
                }
                DecimalFloatingPointString result = default(DecimalFloatingPointString);

                result.Mantissa = mantissaBuilder.ToString();
                if (i < source.Length && (source[i] == 'e' || source[i] == 'E'))
                {
                    const int MAX_EXP      = (1 << 30); // even playing ground
                    char      exponentSign = '\0';
                    i++;
                    if (i < source.Length && (source[i] == '-' || source[i] == '+'))
                    {
                        exponentSign = source[i];
                        i++;
                    }
                    int firstExponent = i;
                    int lastExponent  = i;
                    while (i < source.Length && source[i] >= '0' && source[i] <= '9')
                    {
                        lastExponent = ++i;
                    }


                    if (int.TryParse(source.Substring(firstExponent, lastExponent - firstExponent), out int exponentMagnitude) &&
                        exponentMagnitude <= MAX_EXP)
                    {
                        if (exponentSign == '-')
                        {
                            exponent -= exponentMagnitude;
                        }
                        else
                        {
                            exponent += exponentMagnitude;
                        }
                    }
                    else
                    {
                        exponent = exponentSign == '-' ? -MAX_EXP : MAX_EXP;
                    }
                }
                result.Exponent = exponent;
                return(result);
            }