netmsgs/libnetmsgs/nmLibPack.c
int nmUnpackF64(byte_t buf[], size_t bufSize, double *pVal, NMEndian_T eEndian)
{
  static size_t fvalLen = NMFVAL_LEN_F64;     // message field value length

  uint_t                uMSB;       // Most Signifcant Bytes
  uint_t                uLSB;       // Least Signifcant Bytes
  int                   exponent;   // ieee754 unbiased exponent
  union ieee754_float   f;          // 4-byte floating-point number
  union ieee754_double  d;          // 8-byte floating-point number

  _NM_CHK_MEM(bufSize, fvalLen);

  // 8-byte doubles
  if( sizeof(double) == (size_t)NMFVAL_LEN_F64 )
  {
    switch( eEndian )
    {
      case NMEndianLittle:
        UNPACKLITTLE(buf, &d.d);
        break;
      case NMEndianNative:
        UNPACKNATIVE(buf, &d.d);
        break;
      case NMEndianBig:
      default:
        UNPACKBIG(buf, &d.d);
        break;
    }

    *pVal = d.d;
  }

  else // 4-byte doubles
  {
    _NM_CHK_ARCH(*pVal, (size_t)NMFVAL_LEN_F32);

    switch( eEndian )
    {
      case NMEndianLittle:
        UNPACK64LITTLE(buf, &uMSB, &uLSB);
        break;
      case NMEndianNative:
        UNPACK64NATIVE(buf, &uMSB, &uLSB);
        break;
      case NMEndianBig:
      default:
        UNPACK64BIG(buf, &uMSB, &uLSB);
        break;
    }

    if( ((uMSB >> IEEE754_F64_SIGN_SHIFT) & IEEE754_F64_SIGN_MASK) )
    {
      d.ieee.negative   = 1;
    }
    else
    {
      d.ieee.negative   = 0;
    }
    d.ieee.exponent   = (uMSB >> IEEE754_F64_EXPONENT_SHIFT)
                            & IEEE754_F64_EXPONENT_MASK;
    d.ieee.mantissa0  = (uMSB >> IEEE754_F64_MANTISSA0_SHIFT)
                            & IEEE754_F64_MANTISSA0_MASK;
    d.ieee.mantissa1  = (uLSB >> IEEE754_F64_MANTISSA1_SHIFT)
                            & IEEE754_F64_MANTISSA1_MASK;

    // unbias the exponent
    exponent  = (int)d.ieee.exponent - IEEE754_DOUBLE_BIAS;

    // special Not-a-Number case
    if( ieee754_f64_is_nan(d) )
    {
      f = IEEE754_F32_NaN;
    }

    // special infinity cases
    else if( ieee754_f64_is_inf(d) )
    {
      f = IEEE754_F32_Inf;
    }

    // exponent overflow
    else if( exponent > IEEE754_F32_EXP_MAX )
    {
      f = IEEE754_F32_Inf;
      NMLIB_WARNING("floating-point number overflow.");
    }

    // exponent overflow
    else if( exponent < IEEE754_F32_EXP_MIN )
    {
      f = IEEE754_F32_Zero;
      NMLIB_WARNING("floating-point number underflow.");
    }

    // special zero cases
    else if( ieee754_f64_is_zero(d) )
    {
      f = IEEE754_F32_Zero;
    }

    // "normal" floating-point numbers
    else
    {
      f.ieee.exponent   = (byte_t)(exponent + IEEE754_FLOAT_BIAS);
      f.ieee.mantissa = ( (uint_t)((d.ieee.mantissa0
                                    & IEEE754_F64_MANTISSA0_MASK)
                                << IEEE754_F32_F64_MANTISSA0_SHIFT)
                        | (uint_t)((d.ieee.mantissa1
                                    >> IEEE754_F32_F64_MANTISSA1_SHIFT)
                                & IEEE754_F32_F64_MANTISSA1_MASK) )
                        & IEEE754_F32_MANTISSA_MASK;
      if( (d.ieee.mantissa1 & (uint_t)~IEEE754_F32_F64_MANTISSA1_MASK) != 0 )
      {
        NMLIB_WARNING("floating-point number mantissa truncation.");
      }
    }

    // preserve the sign
    f.ieee.negative   = d.ieee.negative;

    *pVal = (double)f.f;
  }

  return (int)fvalLen;
}
/*!
 * \brief Unpack a 64-bit float from the message buffer.
 *
 * The IEEE 754 64-bit format is used with both the big and little endian byte
 * orders. If the machine architecture only supports 32-bit doubles, then 
 * mantissa truncation will occur.
 *
 * \note
 *  <em>On some machines, while integers were represented in little-endian form,
 *  floating point numbers were represented in big-endian form. Because there
 *  are many floating point formats, and a lack of a standard <b>network</b>
 *  representation, no standard for transferring floating point values has been
 *  made</em> - Wikipedia.
 *
 *  \todo
 *  Detect non-IEEE 754 formats and convert to IEEE 754 prior to packing.
 *
 * \copydoc doc_params_unpack_std
 * \copydoc doc_return_unpack_std 
 */
\brief Unpack a 64-bit float from the message buffer.
The IEEE 754 64-bit format is used with both the big and little endian byte
orders. If the machine architecture only supports 32-bit doubles, then
mantissa truncation will occur.

\note
On some machines, while integers were represented in little-endian form,
floating point numbers were represented in big-endian form. Because there
are many floating point formats, and a lack of a standard network
representation, no standard for transferring floating point values has been
made - Wikipedia.

\todo
Detect non-IEEE 754 formats and convert to IEEE 754 prior to packing.


\ brief Unpack a 64 - bit float from the message buffer . The IEEE 754 64 - bit format is used with both the big and little endian byte orders . If the machine architecture only supports 32 - bit doubles then mantissa truncation will occur . \ note On some machines while integers were represented in little - endian form floating point numbers were represented in big - endian form . Because there are many floating point formats and a lack of a standard network representation no standard for transferring floating point values has been made - Wikipedia . \ todo Detect non - IEEE 754 formats and convert to IEEE 754 prior to packing .
int nmUnpackF64(byte_t buf[], size_t bufSize, double *pVal, NMEndian_T eEndian)
{
  static size_t fvalLen = NMFVAL_LEN_F64;     
  uint_t                uMSB;       
  uint_t                uLSB;       
  int                   exponent;   
  union ieee754_float   f;          
  union ieee754_double  d;          
  _NM_CHK_MEM(bufSize, fvalLen);
  if( sizeof(double) == (size_t)NMFVAL_LEN_F64 )
  {
    switch( eEndian )
    {
      case NMEndianLittle:
        UNPACKLITTLE(buf, &d.d);
        break;
      case NMEndianNative:
        UNPACKNATIVE(buf, &d.d);
        break;
      case NMEndianBig:
      default:
        UNPACKBIG(buf, &d.d);
        break;
    }
    *pVal = d.d;
  }
  else 
  {
    _NM_CHK_ARCH(*pVal, (size_t)NMFVAL_LEN_F32);
    switch( eEndian )
    {
      case NMEndianLittle:
        UNPACK64LITTLE(buf, &uMSB, &uLSB);
        break;
      case NMEndianNative:
        UNPACK64NATIVE(buf, &uMSB, &uLSB);
        break;
      case NMEndianBig:
      default:
        UNPACK64BIG(buf, &uMSB, &uLSB);
        break;
    }
    if( ((uMSB >> IEEE754_F64_SIGN_SHIFT) & IEEE754_F64_SIGN_MASK) )
    {
      d.ieee.negative   = 1;
    }
    else
    {
      d.ieee.negative   = 0;
    }
    d.ieee.exponent   = (uMSB >> IEEE754_F64_EXPONENT_SHIFT)
                            & IEEE754_F64_EXPONENT_MASK;
    d.ieee.mantissa0  = (uMSB >> IEEE754_F64_MANTISSA0_SHIFT)
                            & IEEE754_F64_MANTISSA0_MASK;
    d.ieee.mantissa1  = (uLSB >> IEEE754_F64_MANTISSA1_SHIFT)
                            & IEEE754_F64_MANTISSA1_MASK;
    exponent  = (int)d.ieee.exponent - IEEE754_DOUBLE_BIAS;
    if( ieee754_f64_is_nan(d) )
    {
      f = IEEE754_F32_NaN;
    }
    else if( ieee754_f64_is_inf(d) )
    {
      f = IEEE754_F32_Inf;
    }
    else if( exponent > IEEE754_F32_EXP_MAX )
    {
      f = IEEE754_F32_Inf;
      NMLIB_WARNING("floating-point number overflow.");
    }
    else if( exponent < IEEE754_F32_EXP_MIN )
    {
      f = IEEE754_F32_Zero;
      NMLIB_WARNING("floating-point number underflow.");
    }
    else if( ieee754_f64_is_zero(d) )
    {
      f = IEEE754_F32_Zero;
    }
    else
    {
      f.ieee.exponent   = (byte_t)(exponent + IEEE754_FLOAT_BIAS);
      f.ieee.mantissa = ( (uint_t)((d.ieee.mantissa0
                                    & IEEE754_F64_MANTISSA0_MASK)
                                << IEEE754_F32_F64_MANTISSA0_SHIFT)
                        | (uint_t)((d.ieee.mantissa1
                                    >> IEEE754_F32_F64_MANTISSA1_SHIFT)
                                & IEEE754_F32_F64_MANTISSA1_MASK) )
                        & IEEE754_F32_MANTISSA_MASK;
      if( (d.ieee.mantissa1 & (uint_t)~IEEE754_F32_F64_MANTISSA1_MASK) != 0 )
      {
        NMLIB_WARNING("floating-point number mantissa truncation.");
      }
    }
    f.ieee.negative   = d.ieee.negative;
    *pVal = (double)f.f;
  }
  return (int)fvalLen;
}
int nmUnpackF64 ( byte_t buf [ ] , size_t bufSize , double * pVal , NMEndian_T eEndian ) { static size_t fvalLen = NMFVAL_LEN_F64 ; uint_t uMSB ; uint_t uLSB ; int exponent ; union ieee754_float f ; union ieee754_double d ; _NM_CHK_MEM ( bufSize , fvalLen ) ; if ( sizeof ( double ) == ( size_t ) NMFVAL_LEN_F64 ) { switch ( eEndian ) { case NMEndianLittle : UNPACKLITTLE ( buf , & d . d ) ; break ; case NMEndianNative : UNPACKNATIVE ( buf , & d . d ) ; break ; case NMEndianBig : default : UNPACKBIG ( buf , & d . d ) ; break ; } * pVal = d . d ; } else { _NM_CHK_ARCH ( * pVal , ( size_t ) NMFVAL_LEN_F32 ) ; switch ( eEndian ) { case NMEndianLittle : UNPACK64LITTLE ( buf , & uMSB , & uLSB ) ; break ; case NMEndianNative : UNPACK64NATIVE ( buf , & uMSB , & uLSB ) ; break ; case NMEndianBig : default : UNPACK64BIG ( buf , & uMSB , & uLSB ) ; break ; } if ( ( ( uMSB >> IEEE754_F64_SIGN_SHIFT ) & IEEE754_F64_SIGN_MASK ) ) { d . ieee . negative = 1 ; } else { d . ieee . negative = 0 ; } d . ieee . exponent = ( uMSB >> IEEE754_F64_EXPONENT_SHIFT ) & IEEE754_F64_EXPONENT_MASK ; d . ieee . mantissa0 = ( uMSB >> IEEE754_F64_MANTISSA0_SHIFT ) & IEEE754_F64_MANTISSA0_MASK ; d . ieee . mantissa1 = ( uLSB >> IEEE754_F64_MANTISSA1_SHIFT ) & IEEE754_F64_MANTISSA1_MASK ; exponent = ( int ) d . ieee . exponent - IEEE754_DOUBLE_BIAS ; if ( ieee754_f64_is_nan ( d ) ) { f = IEEE754_F32_NaN ; } else if ( ieee754_f64_is_inf ( d ) ) { f = IEEE754_F32_Inf ; } else if ( exponent > IEEE754_F32_EXP_MAX ) { f = IEEE754_F32_Inf ; NMLIB_WARNING ( " " ) ; } else if ( exponent < IEEE754_F32_EXP_MIN ) { f = IEEE754_F32_Zero ; NMLIB_WARNING ( " " ) ; } else if ( ieee754_f64_is_zero ( d ) ) { f = IEEE754_F32_Zero ; } else { f . ieee . exponent = ( byte_t ) ( exponent + IEEE754_FLOAT_BIAS ) ; f . ieee . mantissa = ( ( uint_t ) ( ( d . ieee . mantissa0 & IEEE754_F64_MANTISSA0_MASK ) << IEEE754_F32_F64_MANTISSA0_SHIFT ) | ( uint_t ) ( ( d . ieee . mantissa1 >> IEEE754_F32_F64_MANTISSA1_SHIFT ) & IEEE754_F32_F64_MANTISSA1_MASK ) ) & IEEE754_F32_MANTISSA_MASK ; if ( ( d . ieee . mantissa1 & ( uint_t ) ~ IEEE754_F32_F64_MANTISSA1_MASK ) != 0 ) { NMLIB_WARNING ( " " ) ; } } f . ieee . negative = d . ieee . negative ; * pVal = ( double ) f . f ; } return ( int ) fvalLen ; }
\brief Unpack a 64-bit float from the message buffer.
\ brief Unpack a 64 - bit float from the message buffer .
// message field value length // Most Signifcant Bytes // Least Signifcant Bytes // ieee754 unbiased exponent // 4-byte floating-point number // 8-byte floating-point number // 8-byte doubles // 4-byte doubles // unbias the exponent // special Not-a-Number case // special infinity cases // exponent overflow // exponent overflow // special zero cases // "normal" floating-point numbers // preserve the sign