// bdldfp_decimalimputil.h -*-C++-*- #ifndef INCLUDED_BDLDFP_DECIMALIMPUTIL #define INCLUDED_BDLDFP_DECIMALIMPUTIL #include <bsls_ident.h> BSLS_IDENT("$Id$") //@PURPOSE: Provide a unified low-level interface for decimal floating point. // //@CLASSES: // bdldfp::DecimalImpUtil: Unified low-level decimal floating point functions. // //@SEE_ALSO: bdldfp_decimalimputil_inteldfp // //@DESCRIPTION: This component provides a namespace, 'bdldfp::DecimalImpUtil', // containing primitive utilities used in the implementation of a decimal // floating point type (e.g., see 'bdldfp_decimal'). // ///Usage ///----- // This section shows the intended use of this component. // ///Example 1: Constructing a Representation of a Value in Decimal /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // A common requirement for decimal floating point types is to be able to // create a value from independent "coefficient" and "exponent" values, where // the resulting decimal has the value 'coefficient * 10 ^ exponent'. In the // following example we use such a 'coefficient' and 'exponent' to create // 'Decimal32', 'Decimal64', and 'Decimal128' values. // // First we define values representing the 'coefficient' and 'exponent' (note // the result should be the value 42.5): //.. // int coefficient = 425; // Yet another name for significand // int exponent = -1; //.. // Then we call 'makeDecimal32', 'makeDecimal64', and 'makeDecimal128' to // construct a 'Decimal32', 'Decimal64', and 'Decimal128' respectively. //.. // bdldfp::DecimalImpUtil::ValueType32 d32 = // bdldfp::DecimalImpUtil::makeDecimalRaw32( coefficient, exponent); // bdldfp::DecimalImpUtil::ValueType64 d64 = // bdldfp::DecimalImpUtil::makeDecimalRaw64( coefficient, exponent); // bdldfp::DecimalImpUtil::ValueType128 d128 = // bdldfp::DecimalImpUtil::makeDecimalRaw128(coefficient, exponent); // // ASSERT(bdldfp::DecimalImpUtil::equal( // bdldfp::DecimalImpUtil::binaryToDecimal32( 42.5), d32)); // ASSERT(bdldfp::DecimalImpUtil::equal( // bdldfp::DecimalImpUtil::binaryToDecimal64( 42.5), d64)); // ASSERT(bdldfp::DecimalImpUtil::equal( // bdldfp::DecimalImpUtil::binaryToDecimal128(42.5), d128)); //.. // ///Example 2: Adding Two Decimal Floating Point Values ///- - - - - - - - - - - - - - - - - - - - - - - - - - // Decimal floating point values are frequently used in arithmetic computations // where the precise representation of decimal values is of paramount // importance (for example, financial calculations, as currency is typically // denominated in base-10 decimal values). In the following example we // demonstrate computing the sum of a sequence of security prices, where each // price is held in a 'DecimalImpUtil::ValueType64' value. // // First, we define the signature of a function that computes the sum of an // array of security prices, and returns that sum as a decimal floating point // value: //.. // bdldfp::DecimalImpUtil::ValueType64 // totalSecurities(bdldfp::DecimalImpUtil::ValueType64 *prices, // int numPrices) // // Return a Decimal Floating Point number representing the arithmetic // // total of the values specified by 'prices' and 'numPrices'. // { //.. // Then, we create a local variable to hold the intermediate sum, and set it to // 0: //.. // bdldfp::DecimalImpUtil::ValueType64 total; // total = bdldfp::DecimalImpUtil::int32ToDecimal64(0); //.. // Next, we loop over the array of 'prices' and add each price to the // intermediate 'total': //.. // for (int i = 0; i < numPrices; ++i) { // total = bdldfp::DecimalImpUtil::add(total, prices[i]); // } //.. // Now, we return the computed total value of the securities: //.. // return total; // } //.. // Notice that 'add' is called as a function, and is not an operator overload // for '+'; this is because the 'bdldfp::DecimalImpUtil' utility is intended to // be used in the implementation of operator overloads on a more full fledged // type. // // Finally, we call the function with some sample data, and check the result: //.. // bdldfp::DecimalImpUtil::ValueType64 data[16]; // // for (int i = 0; i < 16; ++i) { // data[i] = bdldfp::DecimalImpUtil::int32ToDecimal64(i + 1); // } // // bdldfp::DecimalImpUtil::ValueType64 result; // result = totalSecurities(data, 16); // // bdldfp::DecimalImpUtil::ValueType64 expected; // // expected = bdldfp::DecimalImpUtil::int32ToDecimal64(16); // // // Totals of values from 1 to 'x' are '(x * x + x) / 2': // // expected = bdldfp::DecimalImpUtil::add( // bdldfp::DecimalImpUtil::multiply(expected, expected), // expected); // expected = bdldfp::DecimalImpUtil::divide( // expected, // bdldfp::DecimalImpUtil::int32ToDecimal64(2)); // // assert(bdldfp::DecimalImpUtil::equal(expected, result)); //.. // Notice that arithmetic is unwieldy and hard to visualize. This is by // design, as the DecimalImpUtil and subordinate components are not intended // for public consumption, or direct use in decimal arithmetic. #include <bdlscm_version.h> #include <bdldfp_decimalformatconfig.h> #include <bdldfp_decimalimputil_inteldfp.h> #include <bdldfp_decimalplatform.h> #include <bdldfp_decimalstorage.h> #include <bdldfp_intelimpwrapper.h> #include <bdldfp_uint128.h> #include <bslmf_assert.h> #include <bsls_assert.h> #include <bsls_keyword.h> #include <bsls_types.h> #include <bsl_algorithm.h> #include <bsl_cmath.h> #include <bsl_c_errno.h> #include <bsl_iostream.h> #ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #include <bsl_c_signal.h> // Formerly transitively included via decContext.h #endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #ifdef BDLDFP_DECIMALPLATFORM_SOFTWARE // DECIMAL FLOATING-POINT LITERAL EMULATION #define BDLDFP_DECIMALIMPUTIL_DF(lit) \ BloombergLP::bdldfp::DecimalImpUtil::parse32( \ (BloombergLP::bdldfp::DecimalImpUtil::checkLiteral(lit), #lit)) #define BDLDFP_DECIMALIMPUTIL_DD(lit) \ BloombergLP::bdldfp::DecimalImpUtil::parse64( \ (BloombergLP::bdldfp::DecimalImpUtil::checkLiteral(lit), #lit)) #define BDLDFP_DECIMALIMPUTIL_DL(lit) \ BloombergLP::bdldfp::DecimalImpUtil::parse128( \ (BloombergLP::bdldfp::DecimalImpUtil::checkLiteral(lit), #lit)) #elif defined(BDLDFP_DECIMALPLATFORM_C99_TR) || defined( __IBM_DFP__ ) #define BDLDFP_DECIMALIMPUTIL_JOIN_(a,b) a##b // Portable decimal floating-point literal support #define BDLDFP_DECIMALIMPUTIL_DF(lit) BDLDFP_DECIMALIMPUTIL_JOIN_(lit,df) #define BDLDFP_DECIMALIMPUTIL_DD(lit) BDLDFP_DECIMALIMPUTIL_JOIN_(lit,dd) #define BDLDFP_DECIMALIMPUTIL_DL(lit) BDLDFP_DECIMALIMPUTIL_JOIN_(lit,dl) #endif namespace BloombergLP { namespace bdldfp { // ==================== // class DecimalImpUtil // ==================== class DecimalImpUtil { // This 'struct' provides a namespace for utility functions that implement // core decimal floating-poing operations. private: #if defined(BDLDFP_DECIMALPLATFORM_INTELDFP) typedef DecimalImpUtil_IntelDfp Imp; #else BDLDFP_DECIMALPLATFORM_COMPILER_ERROR; #endif public: // TYPES typedef Imp::ValueType32 ValueType32; typedef Imp::ValueType64 ValueType64; typedef Imp::ValueType128 ValueType128; enum { // Status flag bitmask for numeric operations. k_STATUS_INEXACT = Imp::k_STATUS_INEXACT, k_STATUS_UNDERFLOW = Imp::k_STATUS_UNDERFLOW, k_STATUS_OVERFLOW = Imp::k_STATUS_OVERFLOW }; // CLASS METHODS static ValueType64 makeDecimal64( int significand, int exponent); static ValueType64 makeDecimal64(unsigned int significand, int exponent); static ValueType64 makeDecimal64( long long int significand, int exponent); static ValueType64 makeDecimal64(unsigned long long int significand, int exponent); // Return a 'Decimal64' object that has the specified 'significand' and // 'exponent', rounded according to the current decimal rounding mode, // if necessary. If an overflow condition occurs, store the value of // the macro 'ERANGE' into 'errno' and return infinity with the // appropriate sign. static ValueType64 makeInfinity64(bool isNegative = false); // Return a 'ValueType64' representing infinity. Optionally specify // whether the infinity 'isNegative'. If 'isNegative' is 'false' or is // is not supplied, the returned value will be infinity, and negative // infinity otherwise. #ifdef BDLDFP_DECIMALPLATFORM_SOFTWARE // Literal Checking Functions struct This_is_not_a_floating_point_literal {}; // This 'struct' is a helper type used to generate error messages for // bad literals. template <class TYPE> static void checkLiteral(const TYPE& t); // Generate an error if the specified 't' is bad decimal // floating-point. Note that this function is intended for use with // literals static void checkLiteral(double); // Overload to avoid an error when the decimal floating-point literal // (without the suffix) can be interpreted as a 'double' literal. #elif defined(BDLDFP_DECIMALPLATFORM_HARDWARE) #else #error Improperly configured decimal floating point platform settings #endif // classify static int classify(ValueType32 x); static int classify(ValueType64 x); static int classify(ValueType128 x); // Return the integer value that respresents the floating point // classification of the specified 'x' value as follows: // //: o if 'x' is NaN, return FP_NAN; //: o otherwise if 'x' is positive or negative infinity, return //: 'FP_INFINITE'; //: o otherwise if 'x' is a subnormal value, return 'FP_SUBNORMAL' //: o otherwise if 'x' is a zero value, return 'FP_ZERO' //: o otherwise return 'FP_NORMAL' // // Note that the mention 'FP_XXX' constants are C99 standard macros and // they are defined in the math.h (cmath) standard header. On systems // that fail to define those standard macros we define the in this // component as public macros. // normalize static ValueType32 normalize(ValueType32 original); static ValueType64 normalize(ValueType64 original); static ValueType128 normalize(ValueType128 original); // Return a 'ValueTypeXX' number having the value as the specified // 'original, but with the significand, that can not be divided by ten, // and appropriate exponent. // //: o Any representations of zero value (either positive or negative) //: are normalized to positive zero having null significand and //: exponent. //: //: o Any NaN values (either signaling or quiet) are normalized to //: quiet NaN. //: //: o Normalized non-zero value has the same sign as the original one. // Quantum functions static ValueType32 quantize(ValueType32 value, ValueType32 exponent); static ValueType64 quantize(ValueType64 value, ValueType64 exponent); static ValueType128 quantize(ValueType128 value, ValueType128 exponent); // Return a number equal to the specified 'value' (except for possible // rounding) having the exponent equal to the exponent of the specified // 'exponent'. Rounding may occur when the exponent is greater than // the quantum of 'value'. E.g., 'quantize(147e-2_d32, 1e-1_d32)' // yields '15e-1_d32'. In the opposite direction, if 'exponent' is // sufficiently less than the quantum of 'value', it may not be // possible to construct the requested result, and if so, 'NaN' is // returned. E.g., 'quantize(1234567e0_d32, 1e-1_d32)' returns 'NaN'. static ValueType32 quantize(ValueType32 value, int exponent); static ValueType64 quantize(ValueType64 value, int exponent); static ValueType128 quantize(ValueType128 value, int exponent); // Return a number equal to the specified 'value' (except for possible // rounding) having the specified 'exponent'. Rounding may occur when // 'exponent' is greater than the quantum of 'value'. E.g., // 'quantize(147e-2_d32, -1)' yields '15e-1_d32'. In the opposite // direction, if 'exponent' is sufficiently less than the quantum of // 'value', it may not be possible to construct the requested result, // and if so, 'NaN' is returned. E.g., 'quantize(1234567e0_d32, -1)' // returns 'NaN'. Behavior is undefined unless the 'exponent' // satisfies the following conditions //: o for 'Decimal32' type: '-101 <= exponent <= 90' //: o for 'Decimal64' type: '-398 <= exponent <= 369' //: o for 'Decimal128' type: '-6176 <= exponent <= 6111' static int quantizeEqual(ValueType32 *x, ValueType32 y, int exponent); static int quantizeEqual(ValueType64 *x, ValueType64 y, int exponent); static int quantizeEqual(ValueType128 *x, ValueType128 y, int exponent); // If a floating-point number equal to the specified 'y' and having the // specified 'exponent' can be constructed, set that value into the // specified 'x' and return 0. Otherwise, or if 'y' is NaN or // infinity, leave the contents of 'x' unchanged and return a non-zero // value. The behavior is undefined unless 'exponent' satisfies the // following conditions //: o for 'Decimal32' type: '-101 <= exponent <= 90' //: o for 'Decimal64' type: '-398 <= exponent <= 369' //: o for 'Decimal128' type: '-6176 <= exponent <= 6111' // // Example: // 'Decimal32 x;' // 'BSLS_ASSERT(0 == quantizeEqual(&x, 123e+3_d32, 2);' // 'BSLS_ASSERT(1230e+2_d32 == x);' // 'BSLS_ASSERT(0 != quantizeEqual(&x, 123e+3_d32, -2);' // 'BSLS_ASSERT(1230e+2_d32 == x);' static bool sameQuantum(ValueType32 x, ValueType32 y); static bool sameQuantum(ValueType64 x, ValueType64 y); static bool sameQuantum(ValueType128 x, ValueType128 y); // Return 'true' if the specified 'x' and 'y' values have the same // quantum exponents, and 'false' otherwise. If both arguments are NaN // or both arguments are infinity, they have the same quantum // exponents. Note that if exactly one operand is NaN or exactly one // operand is infinity, they do not have the same quantum exponents. // compose and decompose //static ValueType32 composeDecimal32 (DecimalTriple triple); //static ValueType64 composeDecimal64 (DecimalTriple triple); //static ValueType128 composeDecimal128(DecimalTriple triple); // Return a 'ValueTypeXX' number having the value as specified by the // salient attributes of the specified 'triple'. The behavior is // undefined if the 'significand' has too many decimal digits for // 'ValueType', or the 'exponent' is too large for 'ValueType' static int decompose(int *sign, unsigned int *significand, int *exponent, ValueType32 value); static int decompose(int *sign, bsls::Types::Uint64 *significand, int *exponent, ValueType64 value); static int decompose(int *sign, Uint128 *significand, int *exponent, ValueType128 value); // Decompose the specified decimal 'value' into the components of // the decimal floating-point format and load the result into the // specified 'sign', 'significand' and 'exponent' such that // 'value' is equal to 'sign * significand * (10 ** exponent)'. // The special values infinity and NaNs are decomposed to 'sign', // 'exponent' and 'significand' parts, even though they don't have // their normal meaning (except 'sign'). That is those specific values // cannot be restored using these parts, unlike the finite ones. // Return the integer value that represents the floating point // classification of the specified 'value' as follows: // //: o if 'value' is NaN, return FP_NAN; //: o if 'value' is infinity, return 'FP_INFINITE'; //: o if 'value' is a subnormal value, return 'FP_SUBNORMAL'; //: o if 'value' is a zero value, return 'FP_ZERO'; //: o otherwise return 'FP_NORMAL'. // // Note that a decomposed representation may not be unique, // for example 10 can be represented as either '10 * (10 ** 0)' // or '1 * (10 ** 1)'. The returned 'significand' and 'exponent' // reflect the encoded representation of 'value' (i.e., they // reflect the 'quantum' of 'value'). // Format functions static int format(char *buffer, int length, ValueType32 value, const DecimalFormatConfig& cfg); static int format(char *buffer, int length, ValueType64 value, const DecimalFormatConfig& cfg); static int format(char *buffer, int length, ValueType128 value, const DecimalFormatConfig& cfg); // Format the specified 'value', according to the parameters in the // specified 'cfg'. Place the output in the buffer designated by the // specified 'buffer' and 'length', and return the length of the // formatted value. If there is insufficient room in the buffer, its // contents will be left in an unspecified state, with the returned // value indicating the necessary size. This function does not write // a terminating null character. If 'length' is not positive, 'buffer' // is permitted to be null. This can be used to determine the // necessary buffer size. See the Attributes section under // @DESCRIPTION in the component-level documentation for // 'bdldfp::DecimalFormatConfig' component for information on the // configuration attributes. // // Note that for some combinations of 'value' and precision provided by // 'cfg' object, the number being written must first be rounded to // fewer digits than it initially contains. The number written must be // as close as possible to the initial value given the constraints on // precision. The rounding should be done as "round-half-up", i.e., // round up in magnitude when the first of the discarded digits is // between 5 and 9. // // Also note that if the configuration format attribute 'style' is // 'e_NATURAL' then all significand digits of the 'value' are output in // the buffer regardless of the value specified in configuration's // 'precision' attribute. // Integer construction 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 a decimal value initialized to the //: value of '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. 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 a decimal value initialized to the //: value of '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. 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 a decimal value initialized to the //: value of '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 // 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 the maximum value supported by 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 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 the maximum value supported by 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 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 the maximum 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 dividing the value of 'lhs' by the value of 'rhs' //: results in an absolute value that is larger than the maximum //: value supported by the 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 dividing the value of 'lhs' by the value of 'rhs' //: results in an absolute value that is smaller than min value //: supported by 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 result of dividing the value of 'lhs' by the //: value of 'rhs'. // Math functions static ValueType32 copySign(ValueType32 x, ValueType32 y); static ValueType64 copySign(ValueType64 x, ValueType64 y); static ValueType128 copySign(ValueType128 x, ValueType128 y); // Return a decimal value with the magnitude of the specifed 'x' and // the sign of the specified 'y'. If 'x' is NaN, then NaN with the // sign of 'y' is returned. // // Examples: 'copysign( 5.0, -2.0)' ==> -5.0; // 'copysign(-5.0, -2.0)' ==> -5.0 static ValueType32 exp(ValueType32 x); static ValueType64 exp(ValueType64 x); static ValueType128 exp(ValueType128 x); // Return 'e' (Euler's number, 2.7182818) raised to the specified power // 'x'. // // Special value handling: //: o If 'x' is +/-0, 1 is returned. //: o If 'x' is negative infinity, +0 is returned. //: o If 'x' is +infinity, +infinity is returned. //: o If 'x' is quiet NaN, quiet NaN is returned. //: o If 'x' is signaling NaN, quiet NaN is returned and the value of //: the macro 'EDOM' is stored into 'errno'. //: o If 'x' is finite, but the result value is outside the range of //: the return type, store the value of the macro 'ERANGE' into //: 'errno' and +infinity value is returned. static ValueType32 log(ValueType32 x); static ValueType64 log(ValueType64 x); static ValueType128 log(ValueType128 x); // Return the natural (base 'e') logarithm of the specified 'x'. // // Special value handling: //: o If 'x' is +/-0, -infinity is returned and the value of the macro //: 'ERANGE' is stored into 'errno'. //: o If 'x' is 1, +0 is returned. //: o If 'x' is negative, quiet NaN is returned and the value of the //: macro 'EDOM' is stored into 'errno'. //: o If 'x' is +infinity, +infinity is returned. //: o If 'x' is quiet NaN, quiet NaN is returned. //: o If 'x' is signaling NaN, quiet NaN is returned and the value of //: the macro 'EDOM' is stored into 'errno'. static ValueType32 logB(ValueType32 x); static ValueType64 logB(ValueType64 x); static ValueType128 logB(ValueType128 x); // Return the FLT_RADIX-based logarithm (i.e., base 10) of the absolute // value of the specified 'x'. // // Special value handling: //: o If 'x' is +/-0, -infinity is returned and the value of the macro //: 'ERANGE' is stored into 'errno'. //: o If 'x' is 1, +0 is returned. //: o If 'x' is +/-infinity, +infinity is returned. //: o If 'x' is quiet NaN, quiet NaN is returned. //: o If 'x' is signaling NaN, quiet NaN is returned and the value of //: the macro 'EDOM' is stored into 'errno'. // // Examples: 'logB( 10.0)' ==> 1.0; // 'logB(-100.0)' ==> 2.0 static ValueType32 log10(ValueType32 x); static ValueType64 log10(ValueType64 x); static ValueType128 log10(ValueType128 x); // Return the common (base-10) logarithm of the specified 'x'. // // Special value handling: //: o If 'x' is +/-0, -infinity is returned and the value of the macro //: 'ERANGE' is stored into 'errno'. //: o If 'x' is 1, +0 is returned. //: o If 'x' is negative, quiet NaN is returned and the value of the //: macro 'EDOM' is stored into 'errno'. //: o If 'x' is +infinity, +infinity is returned. //: o If 'x' is quiet NaN, quiet NaN is returned. //: o If 'x' is signaling NaN, quiet NaN is returned and the value of //: the macro 'EDOM' is stored into 'errno'. static ValueType32 fmod(ValueType32 x, ValueType32 y); static ValueType64 fmod(ValueType64 x, ValueType64 y); static ValueType128 fmod(ValueType128 x, ValueType128 y); // Return the remainder of the division of the specified 'x' by the // specified 'y'. The returned value has the same sign as 'x' and is // less than 'y' in magnitude. // // Special value handling: //: o If either argument is quiet NaN, quiet NaN is returned. //: o If either argument is signaling NaN, quiet NaN is returned, and //: the value of the macro 'EDOM' is stored into 'errno'. //: o If 'x' is +/-infnity and 'y' is not NaN, quiet NaN is returned //: and the value of the macro 'EDOM' is stored into 'errno'. //: o If 'x' is +/-0 and 'y' is not zero, +/-0 is returned. //: o If 'y' is +/-0, quite NaN is returned and the value of the macro //: 'EDOM' is stored into 'errno'. //: o If 'x' is finite and 'y' is +/-infnity, 'x' is returned. static ValueType32 remainder(ValueType32 x, ValueType32 y); static ValueType64 remainder(ValueType64 x, ValueType64 y); static ValueType128 remainder(ValueType128 x, ValueType128 y); // Return the remainder of the division of the specified 'x' by the // specified 'y'. The remainder of the division operation 'x/y' // calculated by this function is exactly the value 'x - n*y', where // 'n' s the integral value nearest the exact value 'x/y'. When // '|n - x/y| == 0.5', the value 'n' is chosen to be even. Note that // in contrast to 'DecimalImpUtil::fmod()', the returned value is not // guaranteed to have the same sign as 'x'. // // Special value handling: //: o The current rounding mode has no effect. //: o If either argument is quiet NaN, quiet NaN is returned. //: o If either argument is signaling NaN, quiet NaN is returned, and //: the value of the macro 'EDOM' is stored into 'errno'. //: o If 'y' is +/-0, quiet NaN is returned and the value of the macro //: 'EDOM' is stored into 'errno'. //: o If 'x' is +/-infnity and 'y' is not NaN, quiet NaN is returned //: and the value of the macro 'EDOM' is stored into 'errno'. //: o If 'x' is finite and 'y' is +/-infnity, 'x' is returned. static long int lrint(ValueType32 x); static long int lrint(ValueType64 x); static long int lrint(ValueType128 x); static long long int llrint(ValueType32 x); static long long int llrint(ValueType64 x); static long long int llrint(ValueType128 x); // Return an integer value nearest to the specified 'x'. Round 'x' // using the current rounding mode. If 'x' is +/-infnity, NaN (either // signaling or quiet) or the rounded value is outside the range of the // return type, store the value of the macro 'EDOM' into 'errno' and // return implementation-defined value. static ValueType32 nextafter( ValueType32 from, ValueType32 to); static ValueType64 nextafter( ValueType64 from, ValueType64 to); static ValueType128 nextafter( ValueType128 from, ValueType128 to); static ValueType32 nexttoward(ValueType32 from, ValueType128 to); static ValueType64 nexttoward(ValueType64 from, ValueType128 to); static ValueType128 nexttoward(ValueType128 from, ValueType128 to); // Return the next representable value of the specified 'from' in the // direction of the specified 'to'. // // Special value handling: //: o If 'from' equals 'to', 'to' is returned. //: o If either argument is quiet NaN, quiet NaN is returned. //: o If either argument is signaling NaN, quiet NaN is returned and //: the value of the macro 'EDOM' is stored into 'errno'. //: o If 'from' is finite, but the expected result is infinity, //: infinity is returned and the value of the macro 'ERANGE' is //: stored into 'errno'. //: o If 'from' does not equal 'to' and the result is subnormal or //: zero, the value of the macro 'ERANGE' is stored into 'errno'. static ValueType32 pow(ValueType32 base, ValueType32 exp); static ValueType64 pow(ValueType64 base, ValueType64 exp); static ValueType128 pow(ValueType128 base, ValueType128 exp); // Return the value of the specified 'base' raised to the power of the // specified 'exp'. // // Special value handling: //: o If 'base' is finite and negative and 'exp' is finite and //: non-integer, quiet NaN is returned and the value of the macro //: 'EDOM' is stored into 'errno'. //: o If the mathematical result of this function is infinity or //: undefined or a range error due to overflow occurs, infinity is //: returned and the value of the macro 'ERANGE' is stored into //: 'errno'. //: o If a range error occurs due to underflow, the correct result //: (after rounding) is returned and the value of the macro 'ERANGE' //: is stored into 'errno'. //: o If either argument is signaling NaN, quiet NaN is returned and //: the value of the macro 'EDOM' is stored into 'errno'. static ValueType32 ceil(ValueType32 x); static ValueType64 ceil(ValueType64 x); static ValueType128 ceil(ValueType128 x); // Return the smallest integral value that is not less than the // specified 'x'. // // Special value handling: //: o if 'x' is quiet NaN, quiet NaN is returned. //: o If 'x' is signaling NaN, quiet NaN is returned and the value of //: the macro 'EDOM' is stored into 'errno'. //: o if 'x' is +/-infinity or +/-0, it is returned unmodified. // // Examples: 'ceil(0.5)' ==> 1.0; 'ceil(-0.5)' ==> 0.0 static ValueType32 floor(ValueType32 x); static ValueType64 floor(ValueType64 x); static ValueType128 floor(ValueType128 x); // Return the largest integral value that is not greater than the // specified 'x'. // // Special value handling: //: o if 'x' is quiet NaN, quiet NaN is returned. //: o If 'x' is signaling NaN, quiet NaN is returned and the value of //: the macro 'EDOM' is stored into 'errno'. //: o if 'x' is +/-infinity or +/-0, it is returned unmodified. // // Examples: 'floor(0.5)' ==> 0.0; 'floor(-0.5)' ==> -1.0 static ValueType32 round(ValueType32 x); static ValueType64 round(ValueType64 x); static ValueType128 round(ValueType128 x); // Return the integral value nearest to the specified 'x'. Round // halfway cases away from zero, regardless of the current decimal // floating point rounding mode. // // Special value handling: //: o if 'x' is quiet NaN, quiet NaN is returned. //: o If 'x' is signaling NaN, quiet NaN is returned and the value of //: the macro 'EDOM' is stored into 'errno'. //: o if 'x' is +/-infinity or +/-0, it is returned unmodified. // // Examples: 'round(0.5)' ==> 1.0; 'round(-0.5)' ==> -1.0 static long int lround(ValueType32 x); static long int lround(ValueType64 x); static long int lround(ValueType128 x); // Return the integral value nearest to the specified 'x'. Round // halfway cases away from zero, regardless of the current decimal // floating point rounding mode. // // Special value handling: //: o if 'x' is NaN (either quiet or signaling), quiet NaN is returned //: and the value of the macro 'EDOM' is stored into 'errno'. //: o if 'x' is +/-infinity, quite NaN is returned and the value of the //: macro 'EDOM' is stored into 'errno'. //: o If the result of the rounding is outside the range of the return //: type, the macro 'EDOM' is stored into 'errno'. // // Examples: 'lround(0.5)' ==> 1.0; 'lround(-0.5)' ==> -1.0 static ValueType32 round(ValueType32 x, unsigned int precision); static ValueType64 round(ValueType64 x, unsigned int precision); static ValueType128 round(ValueType128 x, unsigned int precision); // Return the specified 'x' value rounded to the specified 'precision'. // Round halfway cases away from zero, regardless of the current // decimal floating point rounding mode. If 'x' is integral, positive // zero, negative zero, NaN, or infinity then return 'x' itself. // // Examples: 'round(3.14159, 3)' ==> 3.142 static ValueType32 trunc(ValueType32 x); static ValueType64 trunc(ValueType64 x); static ValueType128 trunc(ValueType128 x); // Return the nearest integral value that is not greater in absolute // value than the specified 'x'. // // Special value handling: //: o if 'x' is quiet NaN, quiet NaN is returned. //: o If 'x' is signaling NaN, quiet NaN is returned and the value of //: the macro 'EDOM' is stored into 'errno'. //: o if 'x' is +/-infinity or +/-0, it is returned unmodified. // // Examples: 'trunc(0.5)' ==> 0.0; 'trunc(-0.5)' ==> 0.0 static ValueType32 fma(ValueType32 x, ValueType32 y, ValueType32 z); static ValueType64 fma(ValueType64 x, ValueType64 y, ValueType64 z); static ValueType128 fma(ValueType128 x, ValueType128 y, ValueType128 z); // Return, using the specified 'x', 'y', and 'z', the value of the // expression 'x * y + z', rounded as one ternary operation according // to the current decimal floating point rounding mode. // // Special value handling: //: o If 'x' or 'y' are quiet NaN, quiet NaN is returned. //: o If any argument is signaling NaN, quiet NaN is returned and the //: value of the macro 'EDOM' is stored into 'errno'. //: o If 'x*y' is an exact infinity and 'z' is infinity with the //: opposite sign, quiet NaN is returned and the value of the macro //: 'EDOM' is stored into 'errno'. //: o If 'x' is zero and 'y' is infinite or if 'x' is infinite and 'y' //: is zero, and 'z' is not a NaN, then quiet NaN is returned and the //: value of the macro 'EDOM' is stored into 'errno'. //: o If 'x' is zero and 'y' is infinite or if 'x' is infinite and 'y' //: is zero, and 'z' is NaN, then quiet NaN is returned. static ValueType32 fabs(ValueType32 x); static ValueType64 fabs(ValueType64 x); static ValueType128 fabs(ValueType128 x); // Return the absolute value of the specified 'x'. // // Special value handling: //: o if 'x' is NaN (either signaling or quiet), quiet NaN is returned. //: o if 'x' is +/-infinity or +/-0, it is returned unmodified. static ValueType32 sqrt(ValueType32 x); static ValueType64 sqrt(ValueType64 x); static ValueType128 sqrt(ValueType128 x); // Return the square root of the specified 'x'. // // Special value handling: //: o If 'x' is quiet NaN, quiet NaN is returned. //: o If 'x' is signaling NaN, quiet NaN is returned and the value of //: the macro 'EDOM' is stored into 'errno'. //: o If 'x' is less than -0, quiet NaN is returned and the value of //: the macro 'EDOM' is stored into 'errno'. //: o If 'x' is +/-infinity or +/-0, it is returned unmodified. // Negation functions static ValueType32 negate(ValueType32 value); static ValueType64 negate(ValueType64 value); static ValueType128 negate(ValueType128 value); // Return the result of applying the unary negation ('-') operator to // the specified 'value' as described by IEEE-754. Note that decimal // floating point representations can encode signed zero values, thus // negating 0 results in -0 and negating -0 results in 0. // 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 the indicated // result type following the conversion rules as defined by IEEE-754: // //: 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 the //: 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 Otherwise 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 signaling NaN, store the value of the macro 'EDOM' //: into 'errno' and return signaling NaN value. //: //: o Otherwise 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 signaling NaN, store the value of the macro 'EDOM' //: into 'errno' and return signaling NaN value. //: //: o Otherwise 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<Decimal128>::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<Decimal128>::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<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'. // ScaleB 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. // // Special value handling: //: o If 'value' is quiet NaN, quiet NaN is returned. //: o If 'value' is signaling NaN, quiet NaN is returned and the value //: of the macro 'EDOM' is stored into 'errno'. //: o If 'x' is infinite, then infinity is returned. //: o If a range error due to overflow occurs, infinity is returned and //: the value of the macro 'ERANGE' is stored into 'errno'. // Parsing functions static ValueType32 parse32( const char *input); static ValueType64 parse64( const char *input); static ValueType128 parse128(const char *input); static ValueType32 parse32( const char *input, unsigned int *status); static ValueType64 parse64( const char *input, unsigned int *status); static ValueType128 parse128(const char *input, unsigned int *status); // Produce an object of the indicated return type by parsing the // specified 'input' string that represents a floating-point number // (written in either fixed or scientific notation). Optionally // specify 'status' in which to load a bit mask of additional status // information. The resulting decimal object is initialized as follows: // //: o If 'input' does not represent a floating-point value, then return //: a decimal object of the indicated return type initialized to a //: NaN. //: //: o Otherwise if 'input' represents infinity (positive or negative), //: as case-insensitive "Inf" or "Infinity" string, then return a //: decimal object of the indicated return type initialized to //: infinity value with the same sign. //: //: o Otherwise if 'input' represents zero (positive or negative), then //: return a decimal object of the indicated return type initialized //: to zero with the same sign. //: //: o Otherwise if 'str' represents a value that 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 a //: decimal object of the indicated return type initialized to //: infinity with the same sign. //: //: o Otherwise if 'input' represents a value that 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 decimal object of //: the indicated return type initialized to zero with the same sign. //: //: o Otherwise if 'input' has a value that is not exactly //: representable using 'std::numeric_limits<Decimal32>::max_digit' //: decimal digits then return a decimal object of the indicated //: return type initialized to the value represented by 'input' //: rounded according to the rounding direction. //: //: o Otherwise return a decimal object of the indicated return type //: initialized to the decimal value representation of 'input'. // // The '*status', if supplied, mest be 0, and may be loaded with a bit // mask of 'k_STATUS_INEXACT', 'k_STATUS_UNDERFLOW', and // 'k_STATUS_OVERFLOW' indicating wether the conversion from text was // inexact, underflowed, or overflowed (or some combination) // respectively. The behavior is undefined unless '*status' (if // supplied) is 0. // // Note that the parsing follows the rules as specified for the // 'strtod32' function in section 9.6 of the ISO/EIC TR 24732 C Decimal // Floating-Point Technical Report. // // Also note that the quanta of the resultant value is determined by // the number of decimal places starting with the most significand // digit in 'input' string and cannot exceed the maximum number of // digits necessary to differentiate all values of the indicated return // type, for example: // //.. // 'parse32("0.015") => 15e-3' // 'parse32("1.5") => 15e-1' // 'parse32("1.500") => 1500e-3' // 'parse32("1.2345678) => 1234568e-6' //.. // 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 'DecimalStorage::TypeXX' 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. // Functions returning special values static ValueType32 min32() BSLS_KEYWORD_NOEXCEPT; // Return the smallest positive normalized number 'ValueType32' can // represent (IEEE-754: +1e-95). static ValueType32 max32() BSLS_KEYWORD_NOEXCEPT; // Return the largest number 'ValueType32' can represent (IEEE-754: // +9.999999e+96). static ValueType32 epsilon32() BSLS_KEYWORD_NOEXCEPT; // Return the difference between the least representable value of type // 'ValueType32' greater than 1 and 1 (IEEE-754: +1e-6). static ValueType32 roundError32() BSLS_KEYWORD_NOEXCEPT; // Return the maximum rounding error for the 'ValueType32' type. The // actual value returned depends on the current decimal floating point // rounding setting. static ValueType32 denormMin32() BSLS_KEYWORD_NOEXCEPT; // Return the smallest positive denormalized value for the // 'ValueType32' type (IEEE-754: +0.000001e-95). static ValueType32 infinity32() BSLS_KEYWORD_NOEXCEPT; // Return the value that represents positive infinity for the // 'ValueType32' type. static ValueType32 quietNaN32() BSLS_KEYWORD_NOEXCEPT; // Return a value that represents non-signaling NaN for the // 'ValueType32' type. static ValueType32 signalingNaN32() BSLS_KEYWORD_NOEXCEPT; // Return a value that represents signaling NaN for the 'ValueType32' // type. static ValueType64 min64() BSLS_KEYWORD_NOEXCEPT; // Return the smallest positive normalized number 'ValueType64' can // represent (IEEE-754: +1e-383). static ValueType64 max64() BSLS_KEYWORD_NOEXCEPT; // Return the largest number 'ValueType64' can represent (IEEE-754: // +9.999999999999999e+384). static ValueType64 epsilon64() BSLS_KEYWORD_NOEXCEPT; // Return the difference between the least representable value of type // 'ValueType64' greater than 1 and 1 (IEEE-754: +1e-15). static ValueType64 roundError64() BSLS_KEYWORD_NOEXCEPT; // Return the maximum rounding error for the 'ValueType64' type. The // actual value returned depends on the current decimal floating point // rounding setting. static ValueType64 denormMin64() BSLS_KEYWORD_NOEXCEPT; // Return the smallest positive denormalized value for the // 'ValueType64' type (IEEE-754: +0.000000000000001e-383). static ValueType64 infinity64() BSLS_KEYWORD_NOEXCEPT; // Return the value that represents positive infinity for the // 'ValueType64' type. static ValueType64 quietNaN64() BSLS_KEYWORD_NOEXCEPT; // Return a value that represents non-signaling NaN for the // 'ValueType64' type. static ValueType64 signalingNaN64() BSLS_KEYWORD_NOEXCEPT; // Return a value that represents signaling NaN for the 'ValueType64' // type. static ValueType128 min128() BSLS_KEYWORD_NOEXCEPT; // Return the smallest positive normalized number 'ValueType128' can // represent (IEEE-754: +1e-6143). static ValueType128 max128() BSLS_KEYWORD_NOEXCEPT; // Return the largest number 'ValueType128' can represent (IEEE-754: // +9.999999999999999999999999999999999e+6144). static ValueType128 epsilon128() BSLS_KEYWORD_NOEXCEPT; // Return the difference between the least representable value of type // 'ValueType128' greater than 1 and 1 (IEEE-754: +1e-33). static ValueType128 roundError128() BSLS_KEYWORD_NOEXCEPT; // Return the maximum rounding error for the 'ValueType128' type. The // actual value returned depends on the current decimal floating point // rounding setting. static ValueType128 denormMin128() BSLS_KEYWORD_NOEXCEPT; // Return the smallest positive denormalized value for the // 'ValueType128' type (IEEE-754: // +0.000000000000000000000000000000001e-6143). static ValueType128 infinity128() BSLS_KEYWORD_NOEXCEPT; // Return the value that represents positive infinity for the // 'ValueType128' type. static ValueType128 quietNaN128() BSLS_KEYWORD_NOEXCEPT; // Return a value that represents non-signaling NaN for the // 'ValueType128' type. static ValueType128 signalingNaN128() BSLS_KEYWORD_NOEXCEPT; // Return a value that represents signaling NaN for the 'ValueType128' // type. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // -------------------- // class DecimalImpUtil // -------------------- #ifdef BDLDFP_DECIMALPLATFORM_SOFTWARE template <class TYPE> inline void DecimalImpUtil::checkLiteral(const TYPE& t) { (void)static_cast<This_is_not_a_floating_point_literal>(t); } inline void DecimalImpUtil::checkLiteral(double) { } #endif // CLASS METHODS // Integer construction inline DecimalImpUtil::ValueType32 DecimalImpUtil::int32ToDecimal32(int value) { return Imp::int32ToDecimal32(value); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::int32ToDecimal64(int value) { return Imp::int32ToDecimal64(value); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::int32ToDecimal128(int value) { return Imp::int32ToDecimal128(value); } inline DecimalImpUtil::ValueType32 DecimalImpUtil::uint32ToDecimal32(unsigned int value) { return Imp::uint32ToDecimal32(value); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::uint32ToDecimal64(unsigned int value) { return Imp::uint32ToDecimal64(value); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::uint32ToDecimal128(unsigned int value) { return Imp::uint32ToDecimal128(value); } inline DecimalImpUtil::ValueType32 DecimalImpUtil::int64ToDecimal32(long long int value) { return Imp::int64ToDecimal32(value); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::int64ToDecimal64(long long int value) { return Imp::int64ToDecimal64(value); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::int64ToDecimal128(long long int value) { return Imp::int64ToDecimal128(value); } inline DecimalImpUtil::ValueType32 DecimalImpUtil::uint64ToDecimal32(unsigned long long int value) { return Imp::uint64ToDecimal32(value); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::uint64ToDecimal64(unsigned long long int value) { return Imp::uint64ToDecimal64(value); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::uint64ToDecimal128(unsigned long long int value) { return Imp::uint64ToDecimal128(value); } // Arithmetic // Addition Functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::add(DecimalImpUtil::ValueType32 lhs, DecimalImpUtil::ValueType32 rhs) { return Imp::add(lhs, rhs); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::add(DecimalImpUtil::ValueType64 lhs, DecimalImpUtil::ValueType64 rhs) { return Imp::add(lhs, rhs); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::add(DecimalImpUtil::ValueType128 lhs, DecimalImpUtil::ValueType128 rhs) { return Imp::add(lhs, rhs); } // Subtraction Functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::subtract(DecimalImpUtil::ValueType32 lhs, DecimalImpUtil::ValueType32 rhs) { return Imp::subtract(lhs, rhs); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::subtract(DecimalImpUtil::ValueType64 lhs, DecimalImpUtil::ValueType64 rhs) { return Imp::subtract(lhs, rhs); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::subtract(DecimalImpUtil::ValueType128 lhs, DecimalImpUtil::ValueType128 rhs) { return Imp::subtract(lhs, rhs); } // Multiplication Functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::multiply(DecimalImpUtil::ValueType32 lhs, DecimalImpUtil::ValueType32 rhs) { return Imp::multiply(lhs, rhs); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::multiply(DecimalImpUtil::ValueType64 lhs, DecimalImpUtil::ValueType64 rhs) { return Imp::multiply(lhs, rhs); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::multiply(DecimalImpUtil::ValueType128 lhs, DecimalImpUtil::ValueType128 rhs) { return Imp::multiply(lhs, rhs); } // Division Functions // Division Functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::divide(DecimalImpUtil::ValueType32 lhs, DecimalImpUtil::ValueType32 rhs) { return Imp::divide(lhs, rhs); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::divide(DecimalImpUtil::ValueType64 lhs, DecimalImpUtil::ValueType64 rhs) { return Imp::divide(lhs, rhs); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::divide(DecimalImpUtil::ValueType128 lhs, DecimalImpUtil::ValueType128 rhs) { return Imp::divide(lhs, rhs); } inline DecimalImpUtil::ValueType32 DecimalImpUtil::quantize(ValueType32 value, ValueType32 exponent) { DecimalImpUtil::ValueType32 retval; _IDEC_flags flags(0); retval.d_raw = __bid32_quantize(value.d_raw, exponent.d_raw, &flags); return retval; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::quantize(ValueType64 value, ValueType64 exponent) { DecimalImpUtil::ValueType64 retval; _IDEC_flags flags(0); retval.d_raw = __bid64_quantize(value.d_raw, exponent.d_raw, &flags); return retval; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::quantize(ValueType128 value, ValueType128 exponent) { DecimalImpUtil::ValueType128 retval; _IDEC_flags flags(0); retval.d_raw = __bid128_quantize(value.d_raw, exponent.d_raw, &flags); return retval; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::quantize(ValueType32 value, int exponent) { BSLS_ASSERT(-101 <= exponent); BSLS_ASSERT( exponent <= 90); DecimalImpUtil::ValueType32 retval; DecimalImpUtil::ValueType32 exp = DecimalImpUtil::makeDecimalRaw32( 1, exponent); _IDEC_flags flags(0); retval.d_raw = __bid32_quantize(value.d_raw, exp.d_raw, &flags); return retval; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::quantize(ValueType64 value, int exponent) { BSLS_ASSERT(-398 <= exponent); BSLS_ASSERT( exponent <= 369); DecimalImpUtil::ValueType64 retval; DecimalImpUtil::ValueType64 exp = DecimalImpUtil::makeDecimalRaw64( 1, exponent); _IDEC_flags flags(0); retval.d_raw = __bid64_quantize(value.d_raw, exp.d_raw, &flags); return retval; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::quantize(ValueType128 value, int exponent) { BSLS_ASSERT(-6176 <= exponent); BSLS_ASSERT( exponent <= 6111); DecimalImpUtil::ValueType128 retval; DecimalImpUtil::ValueType128 exp = DecimalImpUtil::makeDecimalRaw128( 1, exponent); _IDEC_flags flags(0); retval.d_raw = __bid128_quantize(value.d_raw, exp.d_raw, &flags); return retval; } inline int DecimalImpUtil::quantizeEqual(ValueType32 *x, ValueType32 y, int exponent) { BSLS_ASSERT(x); BSLS_ASSERT(-101 <= exponent); BSLS_ASSERT( exponent <= 90); DecimalImpUtil::ValueType32 retval; DecimalImpUtil::ValueType32 exp = DecimalImpUtil::makeDecimalRaw32( 1, exponent); _IDEC_flags flags(0); retval.d_raw = __bid32_quantize(y.d_raw, exp.d_raw, &flags); if (DecimalImpUtil::equal(retval, y)) { *x = retval; return 0; } return -1; } inline int DecimalImpUtil::quantizeEqual(ValueType64 *x, ValueType64 y, int exponent) { BSLS_ASSERT(x); BSLS_ASSERT(-398 <= exponent); BSLS_ASSERT( exponent <= 369); DecimalImpUtil::ValueType64 retval; DecimalImpUtil::ValueType64 exp = DecimalImpUtil::makeDecimalRaw64( 1, exponent); _IDEC_flags flags(0); retval.d_raw = __bid64_quantize(y.d_raw, exp.d_raw, &flags); if (DecimalImpUtil::equal(retval, y)) { *x = retval; return 0; } return -1; } inline int DecimalImpUtil::quantizeEqual(ValueType128 *x, ValueType128 y, int exponent) { BSLS_ASSERT(x); BSLS_ASSERT(-6176 <= exponent); BSLS_ASSERT( exponent <= 6111); DecimalImpUtil::ValueType128 retval; DecimalImpUtil::ValueType128 exp = DecimalImpUtil::makeDecimalRaw128( 1, exponent); _IDEC_flags flags(0); retval.d_raw = __bid128_quantize(y.d_raw, exp.d_raw, &flags); if (DecimalImpUtil::equal(retval, y)) { *x = retval; return 0; } return -1; } inline bool DecimalImpUtil::sameQuantum(ValueType32 x, ValueType32 y) { return __bid32_sameQuantum(x.d_raw, y.d_raw); } inline bool DecimalImpUtil::sameQuantum(ValueType64 x, ValueType64 y) { return __bid64_sameQuantum(x.d_raw, y.d_raw); } inline bool DecimalImpUtil::sameQuantum(ValueType128 x, ValueType128 y) { return __bid128_sameQuantum(x.d_raw, y.d_raw); } // Math functions inline long int DecimalImpUtil::lrint(ValueType32 x) { _IDEC_flags flags(0); long int ret = __bid32_lrint(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return ret; } inline long int DecimalImpUtil::lrint(ValueType64 x) { _IDEC_flags flags(0); long int ret = __bid64_lrint(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return ret; } inline long int DecimalImpUtil::lrint(ValueType128 x) { _IDEC_flags flags(0); long int ret = __bid128_lrint(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return ret; } inline long long int DecimalImpUtil::llrint(ValueType32 x) { _IDEC_flags flags(0); long long int ret = __bid32_llrint(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return ret; } inline long long int DecimalImpUtil::llrint(ValueType64 x) { _IDEC_flags flags(0); long long int ret = __bid64_llrint(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return ret; } inline long long int DecimalImpUtil::llrint(ValueType128 x) { _IDEC_flags flags(0); long long int ret = __bid128_llrint(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return ret; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::nextafter(ValueType32 x, ValueType32 y) { DecimalImpUtil::ValueType32 retval; _IDEC_flags flags(0); retval.d_raw = __bid32_nextafter(x.d_raw, y.d_raw, &flags); if (BID_OVERFLOW_EXCEPTION & flags || BID_UNDERFLOW_EXCEPTION & flags) { errno = ERANGE; } if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::nextafter(ValueType64 x, ValueType64 y) { DecimalImpUtil::ValueType64 retval; _IDEC_flags flags(0); retval.d_raw = __bid64_nextafter(x.d_raw, y.d_raw, &flags); if (BID_OVERFLOW_EXCEPTION & flags || BID_UNDERFLOW_EXCEPTION & flags) { errno = ERANGE; } if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::nextafter(ValueType128 x, ValueType128 y) { DecimalImpUtil::ValueType128 retval; _IDEC_flags flags(0); retval.d_raw = __bid128_nextafter(x.d_raw, y.d_raw, &flags); if (BID_OVERFLOW_EXCEPTION & flags || BID_UNDERFLOW_EXCEPTION & flags) { errno = ERANGE; } if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::nexttoward(ValueType32 x, ValueType128 y) { DecimalImpUtil::ValueType32 retval; _IDEC_flags flags(0); retval.d_raw = __bid32_nexttoward(x.d_raw, y.d_raw, &flags); if (BID_OVERFLOW_EXCEPTION & flags || BID_UNDERFLOW_EXCEPTION & flags) { errno = ERANGE; } if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::nexttoward(ValueType64 x, ValueType128 y) { DecimalImpUtil::ValueType64 retval; _IDEC_flags flags(0); retval.d_raw = __bid64_nexttoward(x.d_raw, y.d_raw, &flags); if (BID_OVERFLOW_EXCEPTION & flags || BID_UNDERFLOW_EXCEPTION & flags) { errno = ERANGE; } if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::nexttoward(ValueType128 x, ValueType128 y) { DecimalImpUtil::ValueType128 retval; _IDEC_flags flags(0); retval.d_raw = __bid128_nexttoward(x.d_raw, y.d_raw, &flags); if (BID_OVERFLOW_EXCEPTION & flags || BID_UNDERFLOW_EXCEPTION & flags) { errno = ERANGE; } if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::pow(ValueType32 base, ValueType32 exp) { DecimalImpUtil::ValueType32 retval; _IDEC_flags flags(0); retval.d_raw = __bid32_pow(base.d_raw, exp.d_raw, &flags); if (BID_OVERFLOW_EXCEPTION & flags || BID_UNDERFLOW_EXCEPTION & flags || BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::pow(ValueType64 base, ValueType64 exp) { DecimalImpUtil::ValueType64 retval; _IDEC_flags flags(0); retval.d_raw = __bid64_pow(base.d_raw, exp.d_raw, &flags); if (BID_OVERFLOW_EXCEPTION & flags || BID_UNDERFLOW_EXCEPTION & flags || BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::pow(ValueType128 base, ValueType128 exp) { DecimalImpUtil::ValueType128 retval; _IDEC_flags flags(0); retval.d_raw = __bid128_pow(base.d_raw, exp.d_raw, &flags); if (BID_OVERFLOW_EXCEPTION & flags || BID_UNDERFLOW_EXCEPTION & flags || BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::ceil(ValueType32 x) { DecimalImpUtil::ValueType32 retval; _IDEC_flags flags(0); retval.d_raw = __bid32_round_integral_positive(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::ceil(ValueType64 x) { DecimalImpUtil::ValueType64 retval; _IDEC_flags flags(0); retval.d_raw = __bid64_round_integral_positive(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::ceil(ValueType128 x) { DecimalImpUtil::ValueType128 retval; _IDEC_flags flags(0); retval.d_raw = __bid128_round_integral_positive(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::floor(ValueType32 x) { DecimalImpUtil::ValueType32 retval; _IDEC_flags flags(0); retval.d_raw = __bid32_round_integral_negative(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::floor(ValueType64 x) { DecimalImpUtil::ValueType64 retval; _IDEC_flags flags(0); retval.d_raw = __bid64_round_integral_negative(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::floor(ValueType128 x) { DecimalImpUtil::ValueType128 retval; _IDEC_flags flags(0); retval.d_raw = __bid128_round_integral_negative(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::round(ValueType32 x) { DecimalImpUtil::ValueType32 retval; _IDEC_flags flags(0); retval.d_raw = __bid32_round_integral_nearest_away(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::round(ValueType64 x) { DecimalImpUtil::ValueType64 retval; _IDEC_flags flags(0); retval.d_raw = __bid64_round_integral_nearest_away(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::round(ValueType128 x) { DecimalImpUtil::ValueType128 retval; _IDEC_flags flags(0); retval.d_raw = __bid128_round_integral_nearest_away(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline long int DecimalImpUtil::lround(ValueType32 x) { _IDEC_flags flags(0); long int rv = __bid32_lround(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline long int DecimalImpUtil::lround(ValueType64 x) { _IDEC_flags flags(0); long int rv = __bid64_lround(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline long int DecimalImpUtil::lround(ValueType128 x) { _IDEC_flags flags(0); long int rv = __bid128_lround(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::trunc(ValueType32 x) { DecimalImpUtil::ValueType32 retval; _IDEC_flags flags(0); retval.d_raw = __bid32_round_integral_zero(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::trunc(ValueType64 x) { DecimalImpUtil::ValueType64 retval; _IDEC_flags flags(0); retval.d_raw = __bid64_round_integral_zero(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::trunc(ValueType128 x) { DecimalImpUtil::ValueType128 retval; _IDEC_flags flags(0); retval.d_raw = __bid128_round_integral_zero(x.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return retval; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::fma(ValueType32 x, ValueType32 y, ValueType32 z) { ValueType32 rv; _IDEC_flags flags(0); rv.d_raw = __bid32_fma(x.d_raw, y.d_raw, z.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::fma(ValueType64 x, ValueType64 y, ValueType64 z) { ValueType64 rv; _IDEC_flags flags(0); rv.d_raw = __bid64_fma(x.d_raw, y.d_raw, z.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::fma(ValueType128 x, ValueType128 y, ValueType128 z) { ValueType128 rv; _IDEC_flags flags(0); rv.d_raw = __bid128_fma(x.d_raw, y.d_raw, z.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } // Selecting, converting functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::fabs(ValueType32 value) { ValueType32 rv; rv.d_raw = __bid32_abs(value.d_raw); return rv; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::fabs(ValueType64 value) { ValueType64 rv; rv.d_raw = __bid64_abs(value.d_raw); return rv; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::fabs(ValueType128 value) { ValueType128 rv; rv.d_raw = __bid128_abs(value.d_raw); return rv; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::sqrt(ValueType32 value) { ValueType32 rv; _IDEC_flags flags(0); rv.d_raw = __bid32_sqrt(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::sqrt(ValueType64 value) { ValueType64 rv; _IDEC_flags flags(0); rv.d_raw = __bid64_sqrt(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::sqrt(ValueType128 value) { ValueType128 rv; _IDEC_flags flags(0); rv.d_raw = __bid128_sqrt(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::copySign(ValueType32 x, ValueType32 y) { ValueType32 rv; rv.d_raw = __bid32_copySign(x.d_raw, y.d_raw); return rv; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::copySign(ValueType64 x, ValueType64 y) { ValueType64 rv; rv.d_raw = __bid64_copySign(x.d_raw, y.d_raw); return rv; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::copySign(ValueType128 x, ValueType128 y) { ValueType128 rv; rv.d_raw = __bid128_copySign(x.d_raw, y.d_raw); return rv; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::exp(ValueType32 value) { ValueType32 rv; _IDEC_flags flags(0); rv.d_raw = __bid32_exp(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_OVERFLOW_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::exp(ValueType64 value) { ValueType64 rv; _IDEC_flags flags(0); rv.d_raw = __bid64_exp(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_OVERFLOW_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::exp(ValueType128 value) { ValueType128 rv; _IDEC_flags flags(0); rv.d_raw = __bid128_exp(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_OVERFLOW_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::log(ValueType32 value) { ValueType32 rv; _IDEC_flags flags(0); rv.d_raw = __bid32_log(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::log(ValueType64 value) { ValueType64 rv; _IDEC_flags flags(0); rv.d_raw = __bid64_log(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::log(ValueType128 value) { ValueType128 rv; _IDEC_flags flags(0); rv.d_raw = __bid128_log(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::logB(ValueType32 value) { ValueType32 rv; _IDEC_flags flags(0); rv.d_raw = __bid32_logb(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::logB(ValueType64 value) { ValueType64 rv; _IDEC_flags flags(0); rv.d_raw = __bid64_logb(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::logB(ValueType128 value) { ValueType128 rv; _IDEC_flags flags(0); rv.d_raw = __bid128_logb(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::log10(ValueType32 value) { ValueType32 rv; _IDEC_flags flags(0); rv.d_raw = __bid32_log10(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::log10(ValueType64 value) { ValueType64 rv; _IDEC_flags flags(0); rv.d_raw = __bid64_log10(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::log10(ValueType128 value) { ValueType128 rv; _IDEC_flags flags(0); rv.d_raw = __bid128_log10(value.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_ZERO_DIVIDE_EXCEPTION & flags) { errno = ERANGE; } return rv; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::fmod(ValueType32 x, ValueType32 y) { ValueType32 rv; _IDEC_flags flags(0); rv.d_raw = __bid32_fmod(x.d_raw, y.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::fmod(ValueType64 x, ValueType64 y) { ValueType64 rv; _IDEC_flags flags(0); rv.d_raw = __bid64_fmod(x.d_raw, y.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::fmod(ValueType128 x, ValueType128 y) { ValueType128 rv; _IDEC_flags flags(0); rv.d_raw = __bid128_fmod(x.d_raw, y.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline DecimalImpUtil::ValueType32 DecimalImpUtil::remainder(ValueType32 x, ValueType32 y) { ValueType32 rv; _IDEC_flags flags(0); rv.d_raw = __bid32_rem(x.d_raw, y.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::remainder(ValueType64 x, ValueType64 y) { ValueType64 rv; _IDEC_flags flags(0); rv.d_raw = __bid64_rem(x.d_raw, y.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::remainder(ValueType128 x, ValueType128 y) { ValueType128 rv; _IDEC_flags flags(0); rv.d_raw = __bid128_rem(x.d_raw, y.d_raw, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } return rv; } // Negation Functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::negate(DecimalImpUtil::ValueType32 value) { return Imp::negate(value); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::negate(DecimalImpUtil::ValueType64 value) { return Imp::negate(value); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::negate(DecimalImpUtil::ValueType128 value) { return Imp::negate(value); } // Comparison // Less Than Functions inline bool DecimalImpUtil::less(DecimalImpUtil::ValueType32 lhs, DecimalImpUtil::ValueType32 rhs) { return Imp::less(lhs, rhs); } inline bool DecimalImpUtil::less(DecimalImpUtil::ValueType64 lhs, DecimalImpUtil::ValueType64 rhs) { return Imp::less(lhs, rhs); } inline bool DecimalImpUtil::less(DecimalImpUtil::ValueType128 lhs, DecimalImpUtil::ValueType128 rhs) { return Imp::less(lhs, rhs); } // Greater Than Functions inline bool DecimalImpUtil::greater(DecimalImpUtil::ValueType32 lhs, DecimalImpUtil::ValueType32 rhs) { return Imp::greater(lhs, rhs); } inline bool DecimalImpUtil::greater(DecimalImpUtil::ValueType64 lhs, DecimalImpUtil::ValueType64 rhs) { return Imp::greater(lhs, rhs); } inline bool DecimalImpUtil::greater(DecimalImpUtil::ValueType128 lhs, DecimalImpUtil::ValueType128 rhs) { return Imp::greater(lhs, rhs); } // Less Or Equal Functions inline bool DecimalImpUtil::lessEqual(DecimalImpUtil::ValueType32 lhs, DecimalImpUtil::ValueType32 rhs) { return Imp::lessEqual(lhs, rhs); } inline bool DecimalImpUtil::lessEqual(DecimalImpUtil::ValueType64 lhs, DecimalImpUtil::ValueType64 rhs) { return Imp::lessEqual(lhs, rhs); } inline bool DecimalImpUtil::lessEqual(DecimalImpUtil::ValueType128 lhs, DecimalImpUtil::ValueType128 rhs) { return Imp::lessEqual(lhs, rhs); } // Greater Or Equal Functions inline bool DecimalImpUtil::greaterEqual(DecimalImpUtil::ValueType32 lhs, DecimalImpUtil::ValueType32 rhs) { return Imp::greaterEqual(lhs, rhs); } inline bool DecimalImpUtil::greaterEqual(DecimalImpUtil::ValueType64 lhs, DecimalImpUtil::ValueType64 rhs) { return Imp::greaterEqual(lhs, rhs); } inline bool DecimalImpUtil::greaterEqual(DecimalImpUtil::ValueType128 lhs, DecimalImpUtil::ValueType128 rhs) { return Imp::greaterEqual(lhs, rhs); } // Equality Functions inline bool DecimalImpUtil::equal(DecimalImpUtil::ValueType32 lhs, DecimalImpUtil::ValueType32 rhs) { return Imp::equal(lhs, rhs); } inline bool DecimalImpUtil::equal(DecimalImpUtil::ValueType64 lhs, DecimalImpUtil::ValueType64 rhs) { return Imp::equal(lhs, rhs); } inline bool DecimalImpUtil::equal(DecimalImpUtil::ValueType128 lhs, DecimalImpUtil::ValueType128 rhs) { return Imp::equal(lhs, rhs); } // Inequality Functions inline bool DecimalImpUtil::notEqual(DecimalImpUtil::ValueType32 lhs, DecimalImpUtil::ValueType32 rhs) { return Imp::notEqual(lhs, rhs); } inline bool DecimalImpUtil::notEqual(DecimalImpUtil::ValueType64 lhs, DecimalImpUtil::ValueType64 rhs) { return Imp::notEqual(lhs, rhs); } inline bool DecimalImpUtil::notEqual(DecimalImpUtil::ValueType128 lhs, DecimalImpUtil::ValueType128 rhs) { return Imp::notEqual(lhs, rhs); } // Inter-type Conversion functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::convertToDecimal32(const DecimalImpUtil::ValueType64& input) { return Imp::convertToDecimal32(input); } inline DecimalImpUtil::ValueType32 DecimalImpUtil::convertToDecimal32(const DecimalImpUtil::ValueType128& input) { return Imp::convertToDecimal32(input); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::convertToDecimal64 (const DecimalImpUtil::ValueType32& input) { return Imp::convertToDecimal64(input); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::convertToDecimal64(const DecimalImpUtil::ValueType128& input) { return Imp::convertToDecimal64(input); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::convertToDecimal128(const DecimalImpUtil::ValueType32& input) { return Imp::convertToDecimal128(input); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::convertToDecimal128(const DecimalImpUtil::ValueType64& input) { return Imp::convertToDecimal128(input); } // Binary floating point conversion functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::binaryToDecimal32(float value) { return Imp::binaryToDecimal32(value); } inline DecimalImpUtil::ValueType32 DecimalImpUtil::binaryToDecimal32(double value) { return Imp::binaryToDecimal32(value); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::binaryToDecimal64(float value) { return Imp::binaryToDecimal64(value); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::binaryToDecimal64(double value) { return Imp::binaryToDecimal64(value); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::binaryToDecimal128(float value) { return Imp::binaryToDecimal128(value); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::binaryToDecimal128(double value) { return Imp::binaryToDecimal128(value); } // makeDecimalRaw Functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::makeDecimalRaw32(int significand, int exponent) { BSLS_ASSERT(-101 <= exponent); BSLS_ASSERT( exponent <= 90); BSLS_ASSERT(bsl::max(significand, -significand) <= 9999999); return Imp::makeDecimalRaw32(significand, exponent); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::makeDecimalRaw64(unsigned long long significand, int exponent) { BSLS_ASSERT(-398 <= exponent); BSLS_ASSERT( exponent <= 369); BSLS_ASSERT(significand <= 9999999999999999LL); return Imp::makeDecimalRaw64(significand, exponent); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::makeDecimalRaw64(long long significand, int exponent) { BSLS_ASSERT(-398 <= exponent); BSLS_ASSERT( exponent <= 369); BSLS_ASSERT(std::max(significand, -significand) <= 9999999999999999LL); return Imp::makeDecimalRaw64(significand, exponent); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::makeDecimalRaw64(unsigned int significand, int exponent) { BSLS_ASSERT(-398 <= exponent); BSLS_ASSERT( exponent <= 369); return Imp::makeDecimalRaw64(significand, exponent); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::makeDecimalRaw64(int significand, int exponent) { BSLS_ASSERT(-398 <= exponent); BSLS_ASSERT( exponent <= 369); return Imp::makeDecimalRaw64(significand, exponent); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::makeDecimalRaw128(unsigned long long significand, int exponent) { BSLS_ASSERT(-6176 <= exponent); BSLS_ASSERT( exponent <= 6111); return Imp::makeDecimalRaw128(significand, exponent); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::makeDecimalRaw128(long long significand, int exponent) { BSLS_ASSERT(-6176 <= exponent); BSLS_ASSERT( exponent <= 6111); return Imp::makeDecimalRaw128(significand, exponent); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::makeDecimalRaw128(unsigned int significand, int exponent) { BSLS_ASSERT(-6176 <= exponent); BSLS_ASSERT( exponent <= 6111); return Imp::makeDecimalRaw128(significand, exponent); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::makeDecimalRaw128(int significand, int exponent) { BSLS_ASSERT(-6176 <= exponent); BSLS_ASSERT( exponent <= 6111); return Imp::makeDecimalRaw128(significand, exponent); } // IEEE Scale B Functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::scaleB(DecimalImpUtil::ValueType32 value, int exponent) { ValueType32 result; _IDEC_flags flags(0); result.d_raw = __bid32_scalbn(value.d_raw, exponent, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_OVERFLOW_EXCEPTION & flags) { errno = ERANGE; } return result; } inline DecimalImpUtil::ValueType64 DecimalImpUtil::scaleB(DecimalImpUtil::ValueType64 value, int exponent) { ValueType64 result; _IDEC_flags flags(0); result.d_raw = __bid64_scalbn(value.d_raw, exponent, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_OVERFLOW_EXCEPTION & flags) { errno = ERANGE; } return result; } inline DecimalImpUtil::ValueType128 DecimalImpUtil::scaleB(DecimalImpUtil::ValueType128 value, int exponent) { ValueType128 result; _IDEC_flags flags(0); result.d_raw = __bid128_scalbn(value.d_raw, exponent, &flags); if (BID_INVALID_EXCEPTION & flags) { errno = EDOM; } if (BID_OVERFLOW_EXCEPTION & flags) { errno = ERANGE; } return result; } // Parsing functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::parse32(const char *input) { return Imp::parse32(input); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::parse64(const char *input) { return Imp::parse64(input); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::parse128(const char *input) { return Imp::parse128(input); } inline DecimalImpUtil::ValueType32 DecimalImpUtil::parse32(const char *input, unsigned int *status) { BSLS_ASSERT(0 == *status); return Imp::parse32(input, status); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::parse64(const char *input, unsigned int *status) { BSLS_ASSERT(0 == *status); return Imp::parse64(input, status); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::parse128(const char *input, unsigned int *status) { BSLS_ASSERT(0 == *status); return Imp::parse128(input, status); } // Densely Packed Conversion Functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::convertDPDtoBID(DecimalStorage::Type32 dpd) { return Imp::convertDPDtoBID(dpd); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::convertDPDtoBID(DecimalStorage::Type64 dpd) { return Imp::convertDPDtoBID(dpd); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::convertDPDtoBID(DecimalStorage::Type128 dpd) { return Imp::convertDPDtoBID(dpd); } inline DecimalStorage::Type32 DecimalImpUtil::convertBIDtoDPD(ValueType32 value) { return Imp::convertBIDtoDPD(value); } inline DecimalStorage::Type64 DecimalImpUtil::convertBIDtoDPD(ValueType64 value) { return Imp::convertBIDtoDPD(value); } inline DecimalStorage::Type128 DecimalImpUtil::convertBIDtoDPD(ValueType128 value) { return Imp::convertBIDtoDPD(value); } // Binary Integral Conversion Functions inline DecimalImpUtil::ValueType32 DecimalImpUtil::convertFromBID(DecimalStorage::Type32 bid) { return Imp::convertFromBID(bid); } inline DecimalImpUtil::ValueType64 DecimalImpUtil::convertFromBID(DecimalStorage::Type64 bid) { return Imp::convertFromBID(bid); } inline DecimalImpUtil::ValueType128 DecimalImpUtil::convertFromBID(DecimalStorage::Type128 bid) { return Imp::convertFromBID(bid); } inline DecimalStorage::Type32 DecimalImpUtil::convertToBID(ValueType32 value) { return Imp::convertToBID(value); } inline DecimalStorage::Type64 DecimalImpUtil::convertToBID(ValueType64 value) { return Imp::convertToBID(value); } inline DecimalStorage::Type128 DecimalImpUtil::convertToBID(ValueType128 value) { return Imp::convertToBID(value); } } // close package namespace } // close enterprise namespace #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 ----------------------------------