Beispiel #1
0
        /// <summary>
        /// This function is part of the fast track for integer floating point strings.
        /// It takes an integer stored as an array of bytes (lsb first) and converts the value into its FloatingType
        /// representation, storing the bits into "result".  If the value is not
        /// representable, +/-infinity is stored and overflow is reported (since this
        /// function only deals with integers, underflow is impossible).
        /// </summary>
        /// <param name="integerValueAsBytes">the bits of the integer, least significant bits first</param>
        /// <param name="integerBitsOfPrecision">the number of bits of precision in integerValueAsBytes</param>
        /// <param name="hasNonzeroFractionalPart">whether there are nonzero digits after the decimal</param>
        /// <param name="type">the kind of real number to build</param>
        /// <param name="result">the result</param>
        /// <returns>An indicator of the kind of result</returns>
        private static Status ConvertBigIntegerToFloatingPointBits(
            byte[] integerValueAsBytes,
            uint integerBitsOfPrecision,
            bool hasNonzeroFractionalPart,
            FloatingPointType type,
            out ulong result
            )
        {
            int   baseExponent = type.DenormalMantissaBits;
            int   exponent;
            ulong mantissa;
            bool  has_zero_tail   = !hasNonzeroFractionalPart;
            int   topElementIndex = ((int)integerBitsOfPrecision - 1) / 8;

            // The high-order byte of integerValueAsBytes might not have a full eight bits.  However,
            // since the data are stored in quanta of 8 bits, and we really only need around 54
            // bits of mantissa for a double (and fewer for a float), we can just assemble data
            // from the eight high-order bytes and we will get between 59 and 64 bits, which is more
            // than enough.
            int bottomElementIndex = Math.Max(0, topElementIndex - (64 / 8) + 1);

            exponent = baseExponent + bottomElementIndex * 8;
            mantissa = 0;
            for (int i = (int)topElementIndex; i >= bottomElementIndex; i--)
            {
                mantissa <<= 8;
                mantissa  |= integerValueAsBytes[i];
            }
            for (int i = bottomElementIndex - 1; has_zero_tail && i >= 0; i--)
            {
                if (integerValueAsBytes[i] != 0)
                {
                    has_zero_tail = false;
                }
            }

            return(type.AssembleFloatingPointValue(mantissa, exponent, has_zero_tail, out result));
        }
Beispiel #2
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));
        }
Beispiel #3
0
        /// <summary>
        /// This function is part of the fast track for integer floating point strings.  
        /// It takes an integer stored as an array of bytes (lsb first) and converts the value into its FloatingType  
        /// representation, storing the bits into "result".  If the value is not  
        /// representable, +/-infinity is stored and overflow is reported (since this  
        /// function only deals with integers, underflow is impossible).  
        /// </summary>
        /// <param name="integerValueAsBytes">the bits of the integer, least significant bits first</param>
        /// <param name="integerBitsOfPrecision">the number of bits of precision in integerValueAsBytes</param>
        /// <param name="hasNonzeroFractionalPart">whether there are nonzero digits after the decimal</param>
        /// <param name="type">the kind of real number to build</param>
        /// <param name="result">the result</param>
        /// <returns>An indicator of the kind of result</returns>
        private static Status ConvertBigIntegerToFloatingPointBits(byte[] integerValueAsBytes, uint integerBitsOfPrecision, bool hasNonzeroFractionalPart, FloatingPointType type, out ulong result)
        {
            int baseExponent = type.DenormalMantissaBits;
            int exponent;
            ulong mantissa;
            bool has_zero_tail = !hasNonzeroFractionalPart;
            int topElementIndex = ((int)integerBitsOfPrecision - 1) / 8;

            // The high-order byte of integerValueAsBytes might not have a full eight bits.  However,  
            // since the data are stored in quanta of 8 bits, and we really only need around 54  
            // bits of mantissa for a double (and fewer for a float), we can just assemble data  
            // from the eight high-order bytes and we will get between 59 and 64 bits, which is more  
            // than enough.
            int bottomElementIndex = Math.Max(0, topElementIndex - (64 / 8) + 1);
            exponent = baseExponent + bottomElementIndex * 8;
            mantissa = 0;
            for (int i = (int)topElementIndex; i >= bottomElementIndex; i--)
            {
                mantissa <<= 8;
                mantissa |= integerValueAsBytes[i];
            }
            for (int i = bottomElementIndex - 1; has_zero_tail && i >= 0; i--)
            {
                if (integerValueAsBytes[i] != 0) has_zero_tail = false;
            }

            return type.AssembleFloatingPointValue(mantissa, exponent, has_zero_tail, out result);
        }
Beispiel #4
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);
        }
Beispiel #5
0
 public static byte GetByte(this FloatingPointType t)
 {
     return((byte)t);
 }
 /// <summary>
 /// this function  reads settings from xml stream
 /// </summary>
 /// <param name="settings">XmlReader stream</param>
 protected void CommonReadSettings(XmlReader settings)
 {
     RegisterOrderIn32mode = (RegisterOrderEnum)XmlHelper.ReadStandardIntegerValue(settings, m_Tag_RegisterOrderIn32mode);
     FloatingPoint         = (FloatingPointType)XmlHelper.ReadStandardIntegerValue(settings, m_Tag_FloatingPoint);
 }
 /// <summary>
 /// Creator
 /// </summary>
 /// <param name="portSpeed">Baud rate of the communication line.</param>
 /// <param name="TimeoutResponse">Maximum response time this station is willing to wait.</param>
 /// <param name="NumberOfRetries">Maximum number of retries this station will try.</param>
 public ModBus_CommonProtocolParameters(uint portSpeed, uint TimeoutResponse, ushort NumberOfRetries)
     : base(portSpeed, TimeoutResponse, NumberOfRetries)
 {
     RegisterOrderIn32mode = RegisterOrderEnum.Standard_FirstRegisterIsMoreSignificant;
     FloatingPoint         = FloatingPointType.Standard_Modicon;
 }