// bdldfp_decimalimputil_inteldfp.h                                   -*-C++-*-
#ifndef INCLUDED_BDLDFP_DECIMALIMPUTIL_INTELDFP
#define INCLUDED_BDLDFP_DECIMALIMPUTIL_INTELDFP

#include <bsls_ident.h>
BSLS_IDENT("$Id$")

//@PURPOSE: Provide utility to implement decimal 'float's on the Intel library.
//
//@CLASSES:
//  bdldfp::DecimalImpUtil_IntelDfp: Namespace for Intel decimal FP functions
//
//@SEE_ALSO: bdldfp_decimal, bdldfp_decimalplatform
//
//@DESCRIPTION: This component, 'bdldfp::DecimalImpUtil_IntelDfp' is for
// internal use only by the 'bdldfp_decimal*' components.  Direct use of any
// names declared in this component by any other code invokes undefined
// behavior.  In other words: this code may change, disappear, break, move
// without notice, and no support whatsoever will ever be provided for it.
// This component provides implementations of core Decimal Floating Point
// functionality using the Intel DFP library.
//
///Usage
///-----
// This section shows the intended use of this component.

#include <bdlscm_version.h>

#include <bdldfp_decimalplatform.h>
#include <bdldfp_decimalstorage.h>

#ifdef BDLDFP_DECIMALPLATFORM_INTELDFP
#include <bdldfp_intelimpwrapper.h>

#include <bslmf_assert.h>
#include <bslmf_issame.h>
#include <bsls_assert.h>

#include <bsl_locale.h>
#include <bsl_cstring.h>
#include <bsl_c_errno.h>

namespace BloombergLP {
namespace bdldfp {

                          // ==============================
                          // class DecimalImplUtil_IntelDfp
                          // ==============================

struct DecimalImpUtil_IntelDfp {
    // This 'struct' provides a namespace for implementation functions that
    // work in terms of the underlying C-style decimal floating point
    // implementation, Intel's DFP library.

    // TYPES
    struct ValueType32  { BID_UINT32  d_raw; };
    struct ValueType64  { BID_UINT64  d_raw; };
    struct ValueType128 { BID_UINT128 d_raw; };

    enum {
        // Status flag bitmask for numeric operations.

        k_STATUS_INEXACT = BID_INEXACT_EXCEPTION,
        k_STATUS_UNDERFLOW = BID_UNDERFLOW_EXCEPTION,
        k_STATUS_OVERFLOW = BID_OVERFLOW_EXCEPTION
    };

  private:
    // CLASS METHODS
    static void setErrno(_IDEC_flags flags);
        // Convert bit flags from the specified 'flags' into error codes as
        // follows and load the result into a prepocessor macro 'errno':
        //
        //: o flag BID_INVALID_EXCEPTION     => 'errno = EDOM'
        //: o flag BID_OVERFLOW_EXCEPTION    => 'errno = ERANGE'
        //: o flag BID_UNDERFLOW_EXCEPTION   => 'errno = ERANGE'
        //: o flag BID_ZERO_DIVIDE_EXCEPTION => 'errno = ERANGE'

  public:
    // CLASS METHODS

                        // Integer construction (32-bit)

    static ValueType32   int32ToDecimal32 (                   int value);
    static ValueType32  uint32ToDecimal32 (unsigned           int value);
    static ValueType32   int64ToDecimal32 (         long long int value);
    static ValueType32  uint64ToDecimal32 (unsigned long long int value);
        // Return a 'Decimal32' object having the value closest to the
        // specified 'value' following the conversion rules as defined by
        // IEEE-754:
        //
        //: o If 'value' is zero then initialize this object to a zero with an
        //:   unspecified sign and an unspecified exponent.
        //:
        //: o Otherwise if 'value' has a value that is not exactly
        //:   representable using 'std::numeric_limits<Decimal32>::max_digit'
        //:   decimal digits then return the value rounded according to the
        //:   rounding direction.
        //:
        //: o Otherwise initialize this object to the value of the 'value'.
        //
        // The exponent 0 (quantum 1e-6) is preferred during conversion unless
        // it would cause unnecessary loss of precision.

                        // Integer construction (64-bit)

    static ValueType64   int32ToDecimal64 (                   int value);
    static ValueType64  uint32ToDecimal64 (unsigned           int value);
    static ValueType64   int64ToDecimal64 (         long long int value);
    static ValueType64  uint64ToDecimal64 (unsigned long long int value);
        // Return a 'Decimal64' object having the value closest to the
        // specified 'value' following the conversion rules as defined by
        // IEEE-754:
        //
        //: o If 'value' is zero then initialize this object to a zero with an
        //:   unspecified sign and an unspecified exponent.
        //:
        //: o Otherwise if 'value' has a value that is not exactly
        //:   representable using 'std::numeric_limits<Decimal64>::max_digit'
        //:   decimal digits then return 'value' rounded according to the
        //:   rounding direction.
        //:
        //: o Otherwise initialize this object to the value of the 'value'.
        //
        // The exponent 0 (quantum 1e-15) is preferred during conversion unless
        // it would cause unnecessary loss of precision.

                        // Integer construction (128-bit)

    static ValueType128  int32ToDecimal128(                   int value);
    static ValueType128 uint32ToDecimal128(unsigned           int value);
    static ValueType128  int64ToDecimal128(         long long int value);
    static ValueType128 uint64ToDecimal128(unsigned long long int value);
        // Return a 'Decimal128' object having the value closest to the
        // specified 'value' subject to the conversion rules as defined by
        // IEEE-754:
        //
        //: o If 'value' is zero then initialize this object to a zero with an
        //:   unspecified sign and an unspecified exponent.
        //:
        //: o Otherwise if 'value' has a value that is not exactly
        //:   representable using 'std::numeric_limits<Decimal128>::max_digit'
        //:   decimal digits then return 'value' rounded according to the
        //:   rounding direction.
        //:
        //: o Otherwise initialize this object to 'value'.
        //
        // The exponent 0 (quantum 1e-33) is preferred during conversion unless
        // it would cause unnecessary loss of precision.

                        // Arithmetic functions

                        // Addition functions

    static ValueType32  add(ValueType32  lhs,  ValueType32  rhs);
    static ValueType64  add(ValueType64  lhs,  ValueType64  rhs);
    static ValueType128 add(ValueType128 lhs,  ValueType128 rhs);
        // Add the value of the specified 'rhs' to the value of the specified
        // 'lhs' as described by IEEE-754 and return the result.
        //
        //: o If either of 'lhs' or 'rhs' is signaling NaN, then store the
        //:   value of the macro 'EDOM' into 'errno' and return a NaN.
        //:
        //: o Otherwise if either of 'lhs' or 'rhs' is NaN, return a NaN.
        //:
        //: o Otherwise if 'lhs' and 'rhs' are infinities of differing signs,
        //:   store the value of the macro 'EDOM' into 'errno' and return a
        //:   NaN.
        //:
        //: o Otherwise if 'lhs' and 'rhs' are infinities of the same sign then
        //:   return infinity of that sign.
        //:
        //: o Otherwise if 'rhs' is zero (positive or negative), return 'lhs'.
        //:
        //: o Otherwise if the sum of 'lhs' and 'rhs' has an absolute value
        //:   that is larger than max value supported by indicated result type
        //:   then store the value of the macro 'ERANGE' into 'errno' and
        //:   return infinity with the same sign as that result.
        //:
        //: o Otherwise return the sum of the number represented by 'lhs' and
        //:   the number represented by 'rhs'.

                        // Subtraction functions

    static ValueType32  subtract(ValueType32  lhs,  ValueType32  rhs);
    static ValueType64  subtract(ValueType64  lhs,  ValueType64  rhs);
    static ValueType128 subtract(ValueType128 lhs,  ValueType128 rhs);
        // Subtract the value of the specified 'rhs' from the value of the
        // specified 'lhs' as described by IEEE-754 and return the result.
        //
        //: o If either of 'lhs' or 'rhs' is signaling NaN, then store the
        //:   value of the macro 'EDOM' into 'errno' and return a NaN.
        //:
        //: o Otherwise if either of 'lhs' or 'rhs' is NaN, return a NaN.
        //:
        //: o Otherwise if 'lhs' and the 'rhs' have infinity values of the same
        //:   sign, store the value of the macro 'EDOM' into 'errno' and return
        //:   a NaN.
        //:
        //: o Otherwise if 'lhs' and the 'rhs' have infinity values of
        //:   differing signs, then return 'lhs'.
        //:
        //: o Otherwise if 'rhs' has a zero value (positive or negative), then
        //:   return 'lhs'.
        //:
        //: o Otherwise if the subtracting of 'lhs' and 'rhs' has an absolute
        //:   value that is larger than max value supported by indicated result
        //:   type then store the value of the macro 'ERANGE' into 'errno' and
        //:   return infinity with the same sign as that result.
        //:
        //: o Otherwise return the result of subtracting the value of 'rhs'
        //:   from the value of 'lhs'.

                        // Multiplication functions

    static ValueType32  multiply(ValueType32  lhs,  ValueType32  rhs);
    static ValueType64  multiply(ValueType64  lhs,  ValueType64  rhs);
    static ValueType128 multiply(ValueType128 lhs,  ValueType128 rhs);
        // Multiply the value of the specified 'lhs' object by the value of the
        // specified 'rhs' as described by IEEE-754 and return the result.
        //
        //: o If either of 'lhs' or 'rhs' is signaling NaN, then store the
        //:   value of the macro 'EDOM' into 'errno' and return a NaN.
        //:
        //: o Otherwise if either of 'lhs' or 'rhs' is NaN, return a NaN.
        //:
        //: o Otherwise if one of the operands is infinity (positive or
        //:   negative) and the other is zero (positive or negative), then
        //:   store the value of the macro 'EDOM' into 'errno' and return a
        //:   NaN.
        //:
        //: o Otherwise if both 'lhs' and 'rhs' are infinity (positive or
        //:   negative), return infinity.  The sign of the returned value will
        //:   be positive if 'lhs' and 'rhs' have the same sign, and negative
        //:   otherwise.
        //:
        //: o Otherwise, if either 'lhs' or 'rhs' is zero, return zero.  The
        //:   sign of the returned value will be positive if 'lhs' and 'rhs'
        //:   have the same sign, and negative otherwise.
        //:
        //: o Otherwise if the product of 'lhs' and 'rhs' has an absolute value
        //:   that is larger than max value of the indicated result type then
        //:   store the value of the macro 'ERANGE' into 'errno' and return
        //:   infinity with the same sign as that result.
        //:
        //: o Otherwise if the product of 'lhs' and 'rhs' has an absolute value
        //:   that is smaller than min value of the indicated result type then
        //:   store the value of the macro 'ERANGE' into 'errno' and return
        //:   zero with the same sign as that result.
        //:
        //: o Otherwise return the product of the value of 'rhs' and the number
        //:   represented by 'rhs'.

                        // Division functions

    static ValueType32  divide(ValueType32  lhs,  ValueType32  rhs);
    static ValueType64  divide(ValueType64  lhs,  ValueType64  rhs);
    static ValueType128 divide(ValueType128 lhs,  ValueType128 rhs);
        // Divide the value of the specified 'lhs' by the value of the
        // specified 'rhs' as described by IEEE-754, and return the result.
        //
        //: o If either of 'lhs' or 'rhs' is signaling NaN, then store the
        //:   value of the macro 'EDOM' into 'errno' and return a NaN.
        //:
        //: o Otherwise if either of 'lhs' or 'rhs' is NaN, return a NaN.
        //:
        //: o Otherwise if 'lhs' and 'rhs' are both infinity (positive or
        //:   negative) or both zero (positive or negative) then store the
        //:   value of the macro 'EDOM' into 'errno' and return a NaN.
        //:
        //: o Otherwise if 'lhs' has a normal value and 'rhs' has a positive
        //:   zero value, store the value of the macro 'ERANGE' into 'errno'
        //:   and return infinity with the sign of 'lhs'.
        //:
        //: o Otherwise if 'lhs' has a normal value and 'rhs' has a negative
        //:   zero value, store the value of the macro 'ERANGE' into 'errno'
        //:   and return infinity with the opposite sign as 'lhs'.
        //:
        //: o Otherwise if 'lhs' has infinity value and 'rhs' has a positive
        //:   zero value, return infinity with the sign of 'lhs'.
        //:
        //: o Otherwise if 'lhs' has infinity value and 'rhs' has a negative
        //:   zero value, return infinity with the opposite sign as 'lhs'.
        //:
        //: o Otherwise if dividing the value of 'lhs' with the value of 'rhs'
        //:   results in an absolute value that is larger than max value
        //:   supported by the return type then store the value of the macro
        //:   'ERANGE' into 'errno' and return infinity with the same sign as
        //:   that result.
        //:
        //: o Otherwise if dividing the value of 'lhs' with the value of 'rhs'
        //:   results in an absolute value that is smaller than min value
        //:   supported by indicated result type then store the value of the
        //:   macro 'ERANGE' into 'errno'and return zero with the same sign as
        //:   that result.
        //:
        //: o Otherwise return the result of dividing the value of 'lhs' with
        //:   the value of 'rhs'.

                        // Negation functions

    static ValueType32  negate(ValueType32  value);
    static ValueType64  negate(ValueType64  value);
    static ValueType128 negate(ValueType128 value);
        // Return the result of applying the unary - operator to the specified
        // 'value' as described by IEEE-754.  Note that floating-point numbers
        // have signed zero, therefore this operation is not the same as
        // '0-value'.

                        // Comparison functions

                        // Less Than functions

    static bool less(ValueType32  lhs, ValueType32  rhs);
    static bool less(ValueType64  lhs, ValueType64  rhs);
    static bool less(ValueType128 lhs, ValueType128 rhs);
        // Return 'true' if the specified 'lhs' has a value less than the
        // specified 'rhs' and 'false' otherwise.  The value of a 'Decimal64'
        // object 'lhs' is less than that of an object 'rhs' if the
        // 'compareQuietLess' operation (IEEE-754 defined, non-total ordering
        // comparison) considers the underlying IEEE representation of 'lhs' to
        // be less than of that of 'rhs'.  In other words, 'lhs' is less than
        // 'rhs' if:
        //
        //: o neither 'lhs' nor 'rhs' are NaN, or
        //: o 'lhs' is zero (positive or negative) and 'rhs' is positive, or
        //: o 'rhs' is zero (positive or negative) and 'lhs' negative, or
        //: o 'lhs' is not positive infinity, or
        //: o 'lhs' is negative infinity and 'rhs' is not, or
        //: o 'lhs' and 'rhs' both represent a real number and the real number
        //:   of 'lhs' is less than that of 'rhs'
        //
        // If either or both operands are signaling NaN, store the value of the
        // macro 'EDOM' into 'errno' and return 'false'.

                        // Greater Than functions

    static bool greater(ValueType32  lhs, ValueType32  rhs);
    static bool greater(ValueType64  lhs, ValueType64  rhs);
    static bool greater(ValueType128 lhs, ValueType128 rhs);
        // Return 'true' if the specified 'lhs' has a greater value than the
        // specified 'rhs' and 'false' otherwise.  The value of a 'Decimal64'
        // object 'lhs' is greater than that of an object 'rhs' if the
        // 'compareQuietGreater' operation (IEEE-754 defined, non-total
        // ordering comparison) considers the underlying IEEE representation of
        // 'lhs' to be greater than of that of 'rhs'.  In other words, 'lhs' is
        // greater than 'rhs' if:
        //
        //: o neither 'lhs' nor 'rhs' are NaN, or
        //: o 'rhs' is zero (positive or negative) and 'lhs' positive, or
        //: o 'lhs' is zero (positive or negative) and 'rhs' negative, or
        //: o 'lhs' is not negative infinity, or
        //: o 'lhs' is positive infinity and 'rhs' is not, or
        //: o 'lhs' and 'rhs' both represent a real number and the real number
        //:   of 'lhs' is greater than that of 'rhs'
        //
        // If either or both operands are signaling NaN, store the value of the
        // macro 'EDOM' into 'errno' and return 'false'.

                        // Less Or Equal functions

    static bool lessEqual(ValueType32  lhs, ValueType32  rhs);
    static bool lessEqual(ValueType64  lhs, ValueType64  rhs);
    static bool lessEqual(ValueType128 lhs, ValueType128 rhs);
        // Return 'true' if the specified 'lhs' has a value less than or equal
        // the value of the specified 'rhs' and 'false' otherwise.  The value
        // of a 'Decimal64' object 'lhs' is less than or equal to the value of
        // an object 'rhs' if the 'compareQuietLessEqual' operation (IEEE-754
        // defined, non-total ordering comparison) considers the underlying
        // IEEE representation of 'lhs' to be less or equal to that of 'rhs'.
        // In other words, 'lhs' is less or equal than 'rhs' if:
        //
        //: o neither 'lhs' nor 'rhs' are NaN, or
        //: o 'lhs' and 'rhs' are both zero (positive or negative), or
        //: o both 'lhs' and 'rhs' are positive infinity, or
        //: o 'lhs' is negative infinity, or
        //: o 'lhs' and 'rhs' both represent a real number and the real number
        //:   of 'lhs' is less or equal to that of 'rhs'
        //
        // If either or both operands are signaling NaN, store the value of the
        // macro 'EDOM' into 'errno' and return 'false'.

                        // Greater Or Equal functions

    static bool greaterEqual(ValueType32  lhs, ValueType32  rhs);
    static bool greaterEqual(ValueType64  lhs, ValueType64  rhs);
    static bool greaterEqual(ValueType128 lhs, ValueType128 rhs);
        // Return 'true' if the specified 'lhs' has a value greater than or
        // equal to the value of the specified 'rhs' and 'false' otherwise.
        // The value of a 'Decimal64' object 'lhs' is greater or equal to a
        // 'Decimal64' object 'rhs' if the 'compareQuietGreaterEqual' operation
        // (IEEE-754 defined, non-total ordering comparison ) considers the
        // underlying IEEE representation of 'lhs' to be greater or equal to
        // that of 'rhs'.  In other words, 'lhs' is greater than or equal to
        // 'rhs' if:
        //
        //: o neither 'lhs' nor 'rhs' are NaN, or
        //: o 'lhs' and 'rhs' are both zero (positive or negative), or
        //: o both 'lhs' and 'rhs' are negative infinity, or
        //: o 'lhs' is positive infinity, or
        //: o 'lhs' and 'rhs' both represent a real number and the real number
        //:   of 'lhs' is greater or equal to that of 'rhs'
        //
        // If either or both operands are signaling NaN, store the value of the
        // macro 'EDOM' into 'errno' and return 'false'.

                        // Equality functions

    static bool equal(ValueType32  lhs, ValueType32  rhs);
    static bool equal(ValueType64  lhs, ValueType64  rhs);
    static bool equal(ValueType128 lhs, ValueType128 rhs);
        // Return 'true' if the specified 'lhs' and 'rhs' have the same value,
        // and 'false' otherwise.  Two decimal objects have the same value if
        // the 'compareQuietEqual' operation (IEEE-754 defined, non-total
        // ordering comparison) considers the underlying IEEE representations
        // equal.  In other words, two decimal objects have the same value if:
        //
        //: o both have a zero value (positive or negative), or
        //:
        //: o both have the same infinity value (both positive or negative), or
        //:
        //: o both have the value of a real number that are equal, even if they
        //:   are represented differently (cohorts have the same value)
        //
        // If either or both operands are signaling NaN, store the value of the
        // macro 'EDOM' into 'errno' and return 'false'.

                        // Inequality functions

    static bool notEqual(ValueType32  lhs, ValueType32  rhs);
    static bool notEqual(ValueType64  lhs, ValueType64  rhs);
    static bool notEqual(ValueType128 lhs, ValueType128 rhs);
        // Return 'false' if the specified 'lhs' and 'rhs' have the same value,
        // and 'true' otherwise.  Two decimal objects have the same value if
        // the 'compareQuietEqual' operation (IEEE-754 defined, non-total
        // ordering comparison) considers the underlying IEEE representations
        // equal.  In other words, two decimal objects have the same value if:
        //
        //: o both have a zero value (positive or negative), or
        //:
        //: o both have the same infinity value (both positive or negative), or
        //:
        //: o both have the value of a real number that are equal, even if they
        //:   are represented differently (cohorts have the same value)
        //
        // If either or both operands are signaling NaN, store the value of the
        // macro 'EDOM' into 'errno' and return 'false'.

                        // Inter-type Conversion functions

    static ValueType32  convertToDecimal32 (const ValueType64&  input);
    static ValueType32  convertToDecimal32 (const ValueType128& input);
    static ValueType64  convertToDecimal64 (const ValueType32&  input);
    static ValueType64  convertToDecimal64 (const ValueType128& input);
    static ValueType128 convertToDecimal128(const ValueType32&  input);
    static ValueType128 convertToDecimal128(const ValueType64&  input);
        // Convert the specified 'input' to the closest value of indicated
        // result type following the conversion rules:
        //
        //: o If 'input' is signaling NaN, store the value of the macro 'EDOM'
        //:   into 'errno' and return signaling NaN value.
        //:
        //: o If 'input' is NaN, return NaN value.
        //:
        //: o Otherwise if 'input' is infinity (positive or negative), then
        //:   return infinity with the same sign.
        //:
        //: o Otherwise if 'input' is zero (positive or negative), then
        //:   return zero with the same sign.
        //:
        //: o Otherwise if 'input' has an absolute value that is larger than
        //:   maximum or is smaller than minimum value supported by the result
        //:   type, store the value of the macro 'ERANGE' into 'errno' and
        //:   return infinity or zero with the same sign respectively.
        //:
        //: o Otherwise if 'input' has a value that is not exactly
        //:   representable using maximum digit number supported by indicated
        //:   result type then return the 'input' rounded according to the
        //:   rounding direction.
        //:
        //: o Otherwise return 'input' value of the result type.

                        // Binary floating point conversion functions

    static ValueType32 binaryToDecimal32(      float value);
    static ValueType32 binaryToDecimal32(     double value);
        // Create a 'Decimal32' object having the value closest to the
        // specified 'value' following the conversion rules as defined by
        // IEEE-754:
        //
        //: o If 'value' is signaling NaN, store the value of the macro 'EDOM'
        //:   into 'errno' and return signaling NaN value.
        //:
        //: o If 'value' is NaN, return a NaN.
        //:
        //: o Otherwise if 'value' is infinity (positive or negative), then
        //:   return an object equal to infinity with the same sign.
        //:
        //: o Otherwise if 'value' is a zero value, then return an object equal
        //:   to zero with the same sign.
        //:
        //: o Otherwise if 'value' has an absolute value that is larger than
        //:   'std::numeric_limits<Decimal32>::max()' then store the value of
        //:   the macro 'ERANGE' into 'errno' and return infinity with the same
        //:   sign as 'value'.
        //:
        //: o Otherwise if 'value' has an absolute value that is smaller than
        //:   'std::numeric_limits<Decimal32>::min()' then store the value of
        //:   the macro 'ERANGE' into 'errno' and return a zero with the same
        //:   sign as 'value'.
        //:
        //: o Otherwise if 'value' needs more than
        //:   'std::numeric_limits<Decimal32>::max_digit' significant decimal
        //:   digits to represent then return the 'value' rounded according to
        //:   the rounding direction.
        //:
        //: o Otherwise return a 'Decimal32' object representing 'value'.

    static ValueType64 binaryToDecimal64(      float value);
    static ValueType64 binaryToDecimal64(     double value);
        // Create a 'Decimal64' object having the value closest to the
        // specified 'value' following the conversion rules as defined by
        // IEEE-754:
        //
        //: o If 'value' is NaN, return a NaN.
        //:
        //: o Otherwise if 'value' is infinity (positive or negative), then
        //:   return an object equal to infinity with the same sign.
        //:
        //: o Otherwise if 'value' is a zero value, then return an object equal
        //:   to zero with the same sign.
        //:
        //: o Otherwise if 'value' needs more than
        //:   'std::numeric_limits<Decimal64>::max_digit' significant decimal
        //:   digits to represent then return the 'value' rounded according to
        //:   the rounding direction.
        //:
        //: o Otherwise return a 'Decimal64' object representing 'value'.

    static ValueType128 binaryToDecimal128(      float value);
    static ValueType128 binaryToDecimal128(     double value);
        // Create a 'Decimal128' object having the value closest to the
        // specified 'value' following the conversion rules as defined by
        // IEEE-754:
        //
        //: o If 'value' is NaN, return a NaN.
        //:
        //: o Otherwise if 'value' is infinity (positive or negative), then
        //:   return an object equal to infinity with the same sign.
        //:
        //: o Otherwise if 'value' is a zero value, then return an object equal
        //:   to zero with the same sign.
        //:
        //: o Otherwise if 'value' needs more than
        //:   'std::numeric_limits<Decimal128>::max_digit' significant decimal
        //:   digits to represent then return the 'value' rounded according to
        //:   the rounding direction.
        //:
        //: o Otherwise return a 'Decimal128' object representing 'value'.

                        // makeDecimalRaw functions

    static ValueType32  makeDecimalRaw32(int significand, int exponent);
        // Create a 'ValueType32' object representing a decimal floating point
        // number consisting of the specified 'significand' and 'exponent',
        // with the sign given by 'significand'.  The behavior is undefined
        // unless 'abs(significand) <= 9,999,999' and '-101 <= exponent <= 90'.

    static ValueType64 makeDecimalRaw64(unsigned long long int significand,
                                                           int exponent);
    static ValueType64 makeDecimalRaw64(         long long int significand,
                                                           int exponent);
    static ValueType64 makeDecimalRaw64(unsigned           int significand,
                                                           int exponent);
    static ValueType64 makeDecimalRaw64(                   int significand,
                                                           int exponent);
        // Create a 'ValueType64' object representing a decimal floating point
        // number consisting of the specified 'significand' and 'exponent',
        // with the sign given by 'significand'.  The behavior is undefined
        // unless 'abs(significand) <= 9,999,999,999,999,999' and
        // '-398 <= exponent <= 369'.

    static ValueType128 makeDecimalRaw128(unsigned long long int significand,
                                                             int exponent);
    static ValueType128 makeDecimalRaw128(         long long int significand,
                                                             int exponent);
    static ValueType128 makeDecimalRaw128(unsigned           int significand,
                                                             int exponent);
    static ValueType128 makeDecimalRaw128(                   int significand,
                                                             int exponent);
        // Create a 'ValueType128' object representing a decimal floating point
        // number consisting of the specified 'significand' and 'exponent',
        // with the sign given by 'significand'.  The behavior is undefined
        // unless '-6176 <= exponent <= 6111'.

                        // IEEE Scale B functions

    static ValueType32  scaleB(ValueType32  value, int exponent);
    static ValueType64  scaleB(ValueType64  value, int exponent);
    static ValueType128 scaleB(ValueType128 value, int exponent);
        // Return the result of multiplying the specified 'value' by ten raised
        // to the specified 'exponent'.  The quantum of 'value' is scaled
        // according to IEEE 754's 'scaleB' operations.  The result is
        // unspecified if 'value' is NaN or infinity.

                        // Parsing functions

    static ValueType32 parse32 (const char *string);
        // Parse the specified 'string' as a 32 bit decimal floating-point
        // value and return the result.  The parsing is as specified for the
        // 'strtod32' function in section 9.6 of the ISO/EIC TR 24732 C Decimal
        // Floating-Point Technical Report, except that it is unspecified
        // whether the NaNs returned are quiet or signaling.  If 'string'
        // represents a value that absolute value exceeds the maximum value or
        // is less than the smallest value supported by 'ValueType32' type then
        // store the value of the macro 'ERANGE' into 'errno' and return the
        // value initialized to infinity or zero respectively with the same
        // sign as specified in 'string'.  The behavior is undefined unless
        // 'input' represents a valid 32 bit decimalfloating-point number in
        // scientific or fixed notation, and no unrelated characters precede
        // (not even whitespace) that textual representation and a terminating
        // nul character immediately follows it.  Note that this method does
        // not guarantee the behavior of ISO/EIC TR 24732 C when parsing NaN
        // because the AIX compiler intrinsics return a signaling NaN.

    static ValueType64 parse64(const char *string);
        // Parse the specified 'string' string as a 64 bit decimal floating-
        // point value and return the result.  The parsing is as specified for
        // the 'strtod64' function in section 9.6 of the ISO/EIC TR 24732 C
        // Decimal Floating-Point Technical Report, except that it is
        // unspecified whether the NaNs returned are quiet or signaling.  If
        // 'string' represents a value that absolute value exceeds the maximum
        // value or is less than the smallest value supported by 'ValueType63'
        // type then store the value of the macro 'ERANGE' into 'errno' and
        // return the value initialized to infinity or zero respectively with
        // the same sign as specified in 'string'.  The behavior is undefined
        // unless 'input' represents a valid 64 bit decimal floating-point
        // number in scientific or fixed notation, and no unrelated characters
        // precede (not even whitespace) that textual representation and a
        // terminating nul character immediately follows it.  Note that this
        // method does not guarantee the behavior of ISO/EIC TR 24732 C when
        // parsing NaN because the AIX compiler intrinsics return a signaling
        // NaN.

    static ValueType128 parse128(const char *string);
        // Parse the specified 'string' string as a 128 bit decimal floating-
        // point value and return the result.  The parsing is as specified for
        // the 'strtod128' function in section 9.6 of the ISO/EIC TR 24732 C
        // Decimal Floating-Point Technical Report, except that it is
        // unspecified whether the NaNs returned are quiet or signaling. If
        // 'string' represents a value that absolute value exceeds the maximum
        // value or is less than the smallest value supported by 'ValueType128'
        // type then store the value of the macro 'ERANGE' into 'errno' and
        // return the value initialized to infinity or zero respectively with
        // the same sign as specified in 'string'.  The behavior is undefined
        // unless 'input' represents a valid 128 bit decimal floating-point
        // number in scientific or fixed notation, and no unrelated characters
        // precede (not even whitespace) that textual representation and a
        // terminating null character immediately follows it.  Note that this
        // method does not guarantee the behavior of ISO/EIC TR 24732 C when
        // parsing NaN because the AIX compiler intrinsics return a signaling
        // NaN.

    static ValueType32 parse32(const char *string, unsigned int *status);
    static ValueType64 parse64(const char *string, unsigned int *status);
    static ValueType128 parse128(const char *string, unsigned int *status);
        // Parse the specified 'string' string as a decimal floating-point
        // value and return the result, loading the specified 'status' with a
        // bit mask providing additional status information about the result.
        // The supplied '*status' must be 0, and may be loaded with a bit mask
        // of 'k_STATUS_INEXACT', 'k_STATUS_UNDERFLOW', and 'k_STATUS_OVERFLOW'
        // constants indicating wether the conversion from text inexact,
        // underflowed, or overflowed (or some combination) respectively. The
        // parsing is as specified for the 'strtod128' function in section 9.6
        // of the ISO/EIC TR 24732 C Decimal Floating-Point Technical Report,
        // except that it is unspecified whether the NaNs returned are quiet or
        // signaling. The behavior is undefined unless 'input' represents a
        // valid decimal floating-point number in scientific or fixed notation,
        // and no unrelated characters precede (not even whitespace) that
        // textual representation and a terminating null character immediately
        // follows it.  The behavior is undefined unless '*status' is 0.  Note
        // that this method does not guarantee the behavior of ISO/EIC TR 24732
        // C when parsing NaN because the AIX compiler intrinsics return a
        // signaling NaN.  Also note that the intel decimal floating point
        // library documents that inexact, underflow, and overflow are the
        // possible floating point exceptions for this operation.

    // Densely Packed Conversion Functions

    static ValueType32  convertDPDtoBID(DecimalStorage::Type32  dpd);
    static ValueType64  convertDPDtoBID(DecimalStorage::Type64  dpd);
    static ValueType128 convertDPDtoBID(DecimalStorage::Type128 dpd);
        // Return a 'ValueTypeXX' representing the specified 'dpd', which is
        // currently in Densely Packed Decimal (DPD) format.  This format is
        // compatible with the IBM compiler's native type.

    static DecimalStorage::Type32  convertBIDtoDPD(ValueType32  value);
    static DecimalStorage::Type64  convertBIDtoDPD(ValueType64  value);
    static DecimalStorage::Type128 convertBIDtoDPD(ValueType128 value);
        // Return a 'DenselyPackedDecimalImpUtil::StorageTypeXX' representing
        // the specified 'value' in Densely Packed Decimal (DPD) format.  This
        // format is compatible with the IBM compiler's native type.

                        // Binary Integral Conversion Functions

    static ValueType32  convertFromBID(DecimalStorage::Type32  bid);
    static ValueType64  convertFromBID(DecimalStorage::Type64  bid);
    static ValueType128 convertFromBID(DecimalStorage::Type128 bid);
        // Return a 'ValueTypeXX' representing the specified 'bid', which is
        // currently in Binary Integral Decimal (BID) format.  This format is
        // compatible with the Intel DFP implementation type.

    static
    DecimalStorage::Type32  convertToBID(ValueType32  value);
    static
    DecimalStorage::Type64  convertToBID(ValueType64  value);
    static
    DecimalStorage::Type128 convertToBID(ValueType128 value);
        // Return a 'DecimalStorage::TypeXX' representing
        // the specified 'value' in Binary Integral Decimal (BID) format.  This
        // format is compatible with the Intel DFP implementation type.
};

// ============================================================================
//                             INLINE DEFINITIONS
// ============================================================================

                          // -----------------------------
                          // class DecimalImpUtil_IntelDfp
                          // -----------------------------

// CLASS METHODS
inline
void DecimalImpUtil_IntelDfp::setErrno(_IDEC_flags flags)
{
    if (BID_INVALID_EXCEPTION  & flags) {
        errno = EDOM;
    }
    else if (BID_OVERFLOW_EXCEPTION    & flags ||
             BID_UNDERFLOW_EXCEPTION   & flags ||
             BID_ZERO_DIVIDE_EXCEPTION & flags)
    {
        errno = ERANGE;
    }
}

// CLASS METHODS

                        // Integer construction

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::int32ToDecimal32(int value)
{
    DecimalImpUtil_IntelDfp::ValueType32 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid32_from_int32(value, &flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::int32ToDecimal64(int value)
{
    DecimalImpUtil_IntelDfp::ValueType64 retval;
    retval.d_raw = __bid64_from_int32(value);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::int32ToDecimal128(int value)
{
    DecimalImpUtil_IntelDfp::ValueType128 retval;
    retval.d_raw = __bid128_from_int32(value);
    return retval;
}


inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::uint32ToDecimal32(unsigned int value)
{
    DecimalImpUtil_IntelDfp::ValueType32 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid32_from_uint32(value, &flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::uint32ToDecimal64(unsigned int value)
{
    DecimalImpUtil_IntelDfp::ValueType64 retval;
    retval.d_raw = __bid64_from_uint32(value);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::uint32ToDecimal128(unsigned int value)
{
    DecimalImpUtil_IntelDfp::ValueType128 retval;
    retval.d_raw = __bid128_from_uint32(value);
    return retval;
}


inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::int64ToDecimal32(long long int value)
{
    DecimalImpUtil_IntelDfp::ValueType32 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid32_from_int64(value, &flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::int64ToDecimal64(long long int value)
{
    DecimalImpUtil_IntelDfp::ValueType64 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid64_from_int64(value, &flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::int64ToDecimal128(long long int value)
{
    DecimalImpUtil_IntelDfp::ValueType128 retval;
    retval.d_raw = __bid128_from_int64(value);
    return retval;
}


inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::uint64ToDecimal32(unsigned long long int value)
{
    DecimalImpUtil_IntelDfp::ValueType32 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid32_from_uint64(value, &flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::uint64ToDecimal64(unsigned long long int value)
{
    DecimalImpUtil_IntelDfp::ValueType64 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid64_from_uint64(value, &flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::uint64ToDecimal128(unsigned long long int value)
{
    DecimalImpUtil_IntelDfp::ValueType128 retval;
    retval.d_raw = __bid128_from_uint64(value);
    return retval;
}

                        // Arithmetic

                        // Addition Functions

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::add(DecimalImpUtil_IntelDfp::ValueType32 lhs,
                             DecimalImpUtil_IntelDfp::ValueType32 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType32 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid32_add(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::add(DecimalImpUtil_IntelDfp::ValueType64 lhs,
                             DecimalImpUtil_IntelDfp::ValueType64 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType64 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid64_add(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::add(DecimalImpUtil_IntelDfp::ValueType128 lhs,
                             DecimalImpUtil_IntelDfp::ValueType128 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType128 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid128_add(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

                        // Subtraction Functions

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::subtract(DecimalImpUtil_IntelDfp::ValueType32 lhs,
                                  DecimalImpUtil_IntelDfp::ValueType32 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType32 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid32_sub(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::subtract(DecimalImpUtil_IntelDfp::ValueType64 lhs,
                                  DecimalImpUtil_IntelDfp::ValueType64 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType64 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid64_sub(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::subtract(DecimalImpUtil_IntelDfp::ValueType128 lhs,
                                  DecimalImpUtil_IntelDfp::ValueType128 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType128 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid128_sub(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

                        // Multiplication Functions

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::multiply(DecimalImpUtil_IntelDfp::ValueType32 lhs,
                                  DecimalImpUtil_IntelDfp::ValueType32 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType32 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid32_mul(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::multiply(DecimalImpUtil_IntelDfp::ValueType64 lhs,
                                  DecimalImpUtil_IntelDfp::ValueType64 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType64 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid64_mul(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::multiply(DecimalImpUtil_IntelDfp::ValueType128 lhs,
                                  DecimalImpUtil_IntelDfp::ValueType128 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType128 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid128_mul(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

                        // Division Functions

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::divide(DecimalImpUtil_IntelDfp::ValueType32 lhs,
                                DecimalImpUtil_IntelDfp::ValueType32 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType32 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid32_div(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::divide(DecimalImpUtil_IntelDfp::ValueType64 lhs,
                                DecimalImpUtil_IntelDfp::ValueType64 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType64 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid64_div(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::divide(DecimalImpUtil_IntelDfp::ValueType128 lhs,
                                DecimalImpUtil_IntelDfp::ValueType128 rhs)
{
    DecimalImpUtil_IntelDfp::ValueType128 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid128_div(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return retval;
}

                        // Negation Functions

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::negate(DecimalImpUtil_IntelDfp::ValueType32 value)
{
    DecimalImpUtil_IntelDfp::ValueType32 retval;
    retval.d_raw = __bid32_negate(value.d_raw);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::negate(DecimalImpUtil_IntelDfp::ValueType64 value)
{
    DecimalImpUtil_IntelDfp::ValueType64 retval;
    retval.d_raw = __bid64_negate(value.d_raw);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::negate(DecimalImpUtil_IntelDfp::ValueType128 value)
{
    DecimalImpUtil_IntelDfp::ValueType128 retval;
    retval.d_raw = __bid128_negate(value.d_raw);
    return retval;
}

                        // Comparison Functions

                        // Less Than Functions

inline
bool
DecimalImpUtil_IntelDfp::less(DecimalImpUtil_IntelDfp::ValueType32 lhs,
                              DecimalImpUtil_IntelDfp::ValueType32 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid32_quiet_less(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool
DecimalImpUtil_IntelDfp::less(DecimalImpUtil_IntelDfp::ValueType64 lhs,
                              DecimalImpUtil_IntelDfp::ValueType64 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid64_quiet_less(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool
DecimalImpUtil_IntelDfp::less(DecimalImpUtil_IntelDfp::ValueType128 lhs,
                              DecimalImpUtil_IntelDfp::ValueType128 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid128_quiet_less(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

                        // Greater Than Functions

inline
bool
DecimalImpUtil_IntelDfp::greater(DecimalImpUtil_IntelDfp::ValueType32 lhs,
                                 DecimalImpUtil_IntelDfp::ValueType32 rhs)
{
    _IDEC_flags flags(0);
    bool res =  __bid32_quiet_greater(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool DecimalImpUtil_IntelDfp::greater(DecimalImpUtil_IntelDfp::ValueType64 lhs,
                                      DecimalImpUtil_IntelDfp::ValueType64 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid64_quiet_greater(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool
DecimalImpUtil_IntelDfp::greater(DecimalImpUtil_IntelDfp::ValueType128 lhs,
                                 DecimalImpUtil_IntelDfp::ValueType128 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid128_quiet_greater(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

                        // Less Or Equal Functions

inline
bool
DecimalImpUtil_IntelDfp::lessEqual(DecimalImpUtil_IntelDfp::ValueType32 lhs,
                                   DecimalImpUtil_IntelDfp::ValueType32 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid32_quiet_less_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool
DecimalImpUtil_IntelDfp::lessEqual(DecimalImpUtil_IntelDfp::ValueType64 lhs,
                                   DecimalImpUtil_IntelDfp::ValueType64 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid64_quiet_less_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool
DecimalImpUtil_IntelDfp::lessEqual(DecimalImpUtil_IntelDfp::ValueType128 lhs,
                                   DecimalImpUtil_IntelDfp::ValueType128 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid128_quiet_less_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

                        // Greater Or Equal Functions

inline
bool
DecimalImpUtil_IntelDfp::greaterEqual(DecimalImpUtil_IntelDfp::ValueType32 lhs,
                                      DecimalImpUtil_IntelDfp::ValueType32 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid32_quiet_greater_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool
DecimalImpUtil_IntelDfp::greaterEqual(DecimalImpUtil_IntelDfp::ValueType64 lhs,
                                      DecimalImpUtil_IntelDfp::ValueType64 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid64_quiet_greater_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool
DecimalImpUtil_IntelDfp::greaterEqual(
                                     DecimalImpUtil_IntelDfp::ValueType128 lhs,
                                     DecimalImpUtil_IntelDfp::ValueType128 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid128_quiet_greater_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

                        // Equality Functions

inline
bool
DecimalImpUtil_IntelDfp::equal(DecimalImpUtil_IntelDfp::ValueType32 lhs,
                               DecimalImpUtil_IntelDfp::ValueType32 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid32_quiet_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool
DecimalImpUtil_IntelDfp::equal(DecimalImpUtil_IntelDfp::ValueType64 lhs,
                               DecimalImpUtil_IntelDfp::ValueType64 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid64_quiet_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool
DecimalImpUtil_IntelDfp::equal(DecimalImpUtil_IntelDfp::ValueType128 lhs,
                               DecimalImpUtil_IntelDfp::ValueType128 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid128_quiet_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

                        // Inequality Functions

inline
bool
DecimalImpUtil_IntelDfp::notEqual(DecimalImpUtil_IntelDfp::ValueType32 lhs,
                                  DecimalImpUtil_IntelDfp::ValueType32 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid32_quiet_not_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool
DecimalImpUtil_IntelDfp::notEqual(DecimalImpUtil_IntelDfp::ValueType64 lhs,
                                  DecimalImpUtil_IntelDfp::ValueType64 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid64_quiet_not_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

inline
bool
DecimalImpUtil_IntelDfp::notEqual(DecimalImpUtil_IntelDfp::ValueType128 lhs,
                                  DecimalImpUtil_IntelDfp::ValueType128 rhs)
{
    _IDEC_flags flags(0);
    bool res = __bid128_quiet_not_equal(lhs.d_raw, rhs.d_raw, &flags);
    setErrno(flags);
    return res;
}

                        // Inter-type Conversion functions

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::convertToDecimal32(
                             const DecimalImpUtil_IntelDfp::ValueType64& input)
{
    DecimalImpUtil_IntelDfp::ValueType32 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid64_to_bid32(input.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::convertToDecimal32(
                            const DecimalImpUtil_IntelDfp::ValueType128& input)
{
    DecimalImpUtil_IntelDfp::ValueType32 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid128_to_bid32(input.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::convertToDecimal64(
                             const DecimalImpUtil_IntelDfp::ValueType32& input)
{
    DecimalImpUtil_IntelDfp::ValueType64 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid32_to_bid64(input.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::convertToDecimal64(
                            const DecimalImpUtil_IntelDfp::ValueType128& input)
{
    DecimalImpUtil_IntelDfp::ValueType64 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid128_to_bid64(input.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::convertToDecimal128(
                             const DecimalImpUtil_IntelDfp::ValueType32& input)
{
    DecimalImpUtil_IntelDfp::ValueType128 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid32_to_bid128(input.d_raw, &flags);
    setErrno(flags);
    return retval;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::convertToDecimal128(
                             const DecimalImpUtil_IntelDfp::ValueType64& input)
{
    DecimalImpUtil_IntelDfp::ValueType128 retval;
    _IDEC_flags flags(0);
    retval.d_raw = __bid64_to_bid128(input.d_raw, &flags);
    setErrno(flags);
    return retval;
}

                        // Binary floating point conversion functions

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::binaryToDecimal32(float value)
{
    ValueType32 result;
    _IDEC_flags flags(0);
    result.d_raw = __binary32_to_bid32(value, &flags);
    setErrno(flags);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::binaryToDecimal32(double value)
{
    ValueType32 result;
    _IDEC_flags flags(0);
    result.d_raw = __binary64_to_bid32(value, &flags);
    setErrno(flags);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::binaryToDecimal64(float value)
{
    ValueType64 result;
    _IDEC_flags flags(0);
    result.d_raw = __binary32_to_bid64(value, &flags);
    setErrno(flags);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::binaryToDecimal64(double value)
{
    ValueType64 result;
    _IDEC_flags flags(0);
    result.d_raw = __binary64_to_bid64(value, &flags);
    setErrno(flags);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::binaryToDecimal128(float value)
{
    ValueType128 result;
    _IDEC_flags flags(0);
    result.d_raw = __binary32_to_bid128(value, &flags);
    setErrno(flags);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::binaryToDecimal128(double value)
{
    ValueType128 result;
    _IDEC_flags flags(0);
    result.d_raw = __binary64_to_bid128(value, &flags);
    setErrno(flags);
    return result;
}

                        // makeDecimalRaw Functions

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::makeDecimalRaw32(int significand,
                                          int exponent)
{
    DecimalImpUtil_IntelDfp::ValueType32 result;
    result = DecimalImpUtil_IntelDfp::int32ToDecimal32(significand);
    result = DecimalImpUtil_IntelDfp::scaleB(result, exponent);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::makeDecimalRaw64(unsigned long long significand,
                                          int                exponent)
{
    DecimalImpUtil_IntelDfp::ValueType64 result;
    result = DecimalImpUtil_IntelDfp::uint64ToDecimal64(significand);
    result = DecimalImpUtil_IntelDfp::scaleB(result, exponent);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::makeDecimalRaw64(long long significand,
                                          int       exponent)
{
    DecimalImpUtil_IntelDfp::ValueType64 result;
    result = DecimalImpUtil_IntelDfp::int64ToDecimal64(significand);
    result = DecimalImpUtil_IntelDfp::scaleB(result, exponent);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::makeDecimalRaw64(unsigned int significand,
                                          int          exponent)
{
    DecimalImpUtil_IntelDfp::ValueType64 result;
    result = DecimalImpUtil_IntelDfp::uint32ToDecimal64(significand);
    result = DecimalImpUtil_IntelDfp::scaleB(result, exponent);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::makeDecimalRaw64(int significand,
                                          int exponent)
{
    DecimalImpUtil_IntelDfp::ValueType64 result;
    result = DecimalImpUtil_IntelDfp::int32ToDecimal64(significand);
    result = DecimalImpUtil_IntelDfp::scaleB(result, exponent);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::makeDecimalRaw128(unsigned long long significand,
                                           int                exponent)
{
    DecimalImpUtil_IntelDfp::ValueType128 result;
    result = DecimalImpUtil_IntelDfp::uint64ToDecimal128(significand);
    result = DecimalImpUtil_IntelDfp::scaleB(result, exponent);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::makeDecimalRaw128(long long significand,
                                           int       exponent)
{
    DecimalImpUtil_IntelDfp::ValueType128 result;
    result = DecimalImpUtil_IntelDfp::int64ToDecimal128(significand);
    result = DecimalImpUtil_IntelDfp::scaleB(result, exponent);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::makeDecimalRaw128(unsigned int significand,
                                           int          exponent)
{
    DecimalImpUtil_IntelDfp::ValueType128 result;
    result = DecimalImpUtil_IntelDfp::uint32ToDecimal128(significand);
    result = DecimalImpUtil_IntelDfp::scaleB(result, exponent);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::makeDecimalRaw128(int significand,
                                           int exponent)
{
    DecimalImpUtil_IntelDfp::ValueType128 result;
    result = DecimalImpUtil_IntelDfp::int32ToDecimal128(significand);
    result = DecimalImpUtil_IntelDfp::scaleB(result, exponent);
    return result;
}

                        // IEEE Scale B Functions

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::scaleB(DecimalImpUtil_IntelDfp::ValueType32 value,
                                int                                  exponent)
{
    DecimalImpUtil_IntelDfp::ValueType32 result;
    _IDEC_flags flags(0);
    result.d_raw = __bid32_scalbn(value.d_raw, exponent, &flags);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::scaleB(DecimalImpUtil_IntelDfp::ValueType64 value,
                                int                                  exponent)
{
    DecimalImpUtil_IntelDfp::ValueType64 result;
    _IDEC_flags flags(0);
    result.d_raw = __bid64_scalbn(value.d_raw, exponent, &flags);
    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::scaleB(DecimalImpUtil_IntelDfp::ValueType128 value,
                                int                                   exponent)
{
    DecimalImpUtil_IntelDfp::ValueType128 result;
    _IDEC_flags flags(0);
    result.d_raw = __bid128_scalbn(value.d_raw, exponent, &flags);
    return result;
}

                        // Parsing functions

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::parse32(const char *string)
{
    DecimalImpUtil_IntelDfp::ValueType32 result;
    _IDEC_flags flags(0);
    // NOTE: It is probably safe to convert from a 'const char *' to a 'char *'
    // because the __bid* interfaces are C interfaces.
    result.d_raw = __bid32_from_string(const_cast<char *>(string), &flags);

    if (BID_OVERFLOW_EXCEPTION  & flags ||
        BID_UNDERFLOW_EXCEPTION & flags)
    {
        errno = ERANGE;
    }

    return result;
}


inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::parse64(const char *string)
{
    DecimalImpUtil_IntelDfp::ValueType64 result;
    _IDEC_flags flags(0);
    // NOTE: It is probably safe to convert from a 'const char *' to a 'char *'
    // because the __bid* interfaces are C interfaces.
    result.d_raw = __bid64_from_string(const_cast<char *>(string), &flags);

    if (BID_OVERFLOW_EXCEPTION  & flags ||
        BID_UNDERFLOW_EXCEPTION & flags)
    {
        errno = ERANGE;
    }

    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::parse128(const char *string)
{
    DecimalImpUtil_IntelDfp::ValueType128 result;
    _IDEC_flags flags(0);
    // NOTE: It is probably safe to convert from a 'const char *' to a 'char *'
    // because the __bid* interfaces are C interfaces.
    result.d_raw = __bid128_from_string(const_cast<char *>(string), &flags);

    if (BID_OVERFLOW_EXCEPTION  & flags ||
        BID_UNDERFLOW_EXCEPTION & flags)
    {
        errno = ERANGE;
    }

    return result;
}


inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::parse32(const char *string, unsigned int *status)
{
    BSLS_ASSERT(0 == *status);

    DecimalImpUtil_IntelDfp::ValueType32 result;
    BSLMF_ASSERT((bsl::is_same<_IDEC_flags, unsigned int>::value));

    // NOTE: It is probably safe to convert from a 'const char *' to a 'char *'
    // because the __bid* interfaces are C interfaces.  Also note that inexact,
    // underflow, and overflow are the only dcoumented floating point
    // exceptions for this function.

    result.d_raw = __bid32_from_string(const_cast<char *>(string), status);

    return result;
}


inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::parse64(const char *string, unsigned int *status)
{
    BSLS_ASSERT(0 == *status);

    DecimalImpUtil_IntelDfp::ValueType64 result;

    BSLMF_ASSERT((bsl::is_same<_IDEC_flags, unsigned int>::value));

    // NOTE: It is probably safe to convert from a 'const char *' to a 'char *'
    // because the __bid* interfaces are C interfaces.  Also note that inexact,
    // underflow, and overflow are the only dcoumented floating point
    // exceptions for this function.

    result.d_raw = __bid64_from_string(const_cast<char *>(string), status);

    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::parse128(const char *string, unsigned int *status)
{
    BSLS_ASSERT(0 == *status);

    DecimalImpUtil_IntelDfp::ValueType128 result;
    BSLMF_ASSERT((bsl::is_same<_IDEC_flags, unsigned int>::value));

    // NOTE: It is probably safe to convert from a 'const char *' to a 'char *'
    // because the __bid* interfaces are C interfaces.  Also note that inexact,
    // underflow, and overflow are the only dcoumented floating point
    // exceptions for this function.

    result.d_raw = __bid128_from_string(const_cast<char *>(string), status);

    return result;
}

                        // Densely Packed Conversion Functions
inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::convertDPDtoBID(DecimalStorage::Type32 dpd)
{
    ValueType32 value;
    bsl::memcpy(&value, &dpd, sizeof(value));

    ValueType32 result;
    result.d_raw = __bid_dpd_to_bid32(value.d_raw);

    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::convertDPDtoBID(DecimalStorage::Type64 dpd)
{
    ValueType64 value;
    bsl::memcpy(&value, &dpd, sizeof(value));

    ValueType64 result;
    result.d_raw = __bid_dpd_to_bid64(value.d_raw);

    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::convertDPDtoBID(DecimalStorage::Type128 dpd)
{
    ValueType128 value;
    bsl::memcpy(&value, &dpd, sizeof(value));

    ValueType128 result;
    result.d_raw = __bid_dpd_to_bid128(value.d_raw);

    return result;
}

inline
DecimalStorage::Type32
DecimalImpUtil_IntelDfp::convertBIDtoDPD(
                                    DecimalImpUtil_IntelDfp::ValueType32 value)
{
    ValueType32 result;
    result.d_raw = __bid_to_dpd32(value.d_raw);

    DecimalStorage::Type32 dpd;
    bsl::memcpy(&dpd, &result, sizeof(dpd));

    return dpd;
}

inline
DecimalStorage::Type64
DecimalImpUtil_IntelDfp::convertBIDtoDPD(
                                    DecimalImpUtil_IntelDfp::ValueType64 value)
{
    ValueType64 result;
    result.d_raw = __bid_to_dpd64(value.d_raw);

    DecimalStorage::Type64 dpd;
    bsl::memcpy(&dpd, &result, sizeof(dpd));

    return dpd;
}

inline
DecimalStorage::Type128
DecimalImpUtil_IntelDfp::convertBIDtoDPD(
                                   DecimalImpUtil_IntelDfp::ValueType128 value)
{
    ValueType128 result;
    result.d_raw = __bid_to_dpd128(value.d_raw);

    DecimalStorage::Type128 dpd;
    bsl::memcpy(&dpd, &result, sizeof(dpd));

    return dpd;
}
                        // Binary Integral Conversion Functions

inline
DecimalImpUtil_IntelDfp::ValueType32
DecimalImpUtil_IntelDfp::convertFromBID(DecimalStorage::Type32 bid)
{
    ValueType32 result;
    bsl::memcpy(&result, &bid, sizeof(result));

    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType64
DecimalImpUtil_IntelDfp::convertFromBID(DecimalStorage::Type64 bid)
{
    ValueType64 result;
    bsl::memcpy(&result, &bid, sizeof(result));

    return result;
}

inline
DecimalImpUtil_IntelDfp::ValueType128
DecimalImpUtil_IntelDfp::convertFromBID(DecimalStorage::Type128 bid)
{
    ValueType128 result;
    bsl::memcpy(&result, &bid, sizeof(result));

    return result;
}

inline
DecimalStorage::Type32
DecimalImpUtil_IntelDfp::convertToBID(
                                    DecimalImpUtil_IntelDfp::ValueType32 value)
{
    DecimalStorage::Type32 bid;
    bsl::memcpy(&bid, &value, sizeof(bid));

    return bid;
}

inline
DecimalStorage::Type64
DecimalImpUtil_IntelDfp::convertToBID(
                                    DecimalImpUtil_IntelDfp::ValueType64 value)
{
    DecimalStorage::Type64 bid;
    bsl::memcpy(&bid, &value, sizeof(bid));

    return bid;
}

inline
DecimalStorage::Type128
DecimalImpUtil_IntelDfp::convertToBID(
                                   DecimalImpUtil_IntelDfp::ValueType128 value)
{
    DecimalStorage::Type128 bid;
    bsl::memcpy(&bid, &value, sizeof(bid));

    return bid;
}

}  // close package namespace
}  // close enterprise namespace

#endif  // #ifdef BDLDFP_DECIMALPLATFORM_INTELDFP

#endif

// ----------------------------------------------------------------------------
// Copyright 2014 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------