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