// bdldfp_decimalconvertutil_inteldfp.h -*-C++-*- #ifndef INCLUDED_BDLDFP_DECIMALCONVERTUTIL_INTELDFP #define INCLUDED_BDLDFP_DECIMALCONVERTUTIL_INTELDFP #include <bsls_ident.h> BSLS_IDENT("$Id$") //@PURPOSE: Provide decimal floating-point conversion functions for Intel DFP. // //@CLASSES: // bdldfp::DecimalConvertUtil_IntelDfp: Intel DFP conversion functions // //@SEE_ALSO: bdldfp_decimal, bdldfp_decimalplatform // //@DESCRIPTION: This component provides conversion operations between the // decimal types supplied in this package ('Decimal32', 'Decimal64', // 'Decimal128') and various alternative representations. Some of the // alternative representations that this component provides conversions for are // IEEE-754 binary floating point (i.e., 'float' and 'double') and a network // format (big-endian, Densely Packed Decimal encoding). // ///Usage ///----- // This section shows the intended use of this component. // ///Example 1: TBD /// - - - - - - - #include <bdlscm_version.h> #include <bdldfp_decimalplatform.h> #ifdef BDLDFP_DECIMALPLATFORM_INTELDFP #include <bdldfp_decimal.h> #include <bdldfp_decimalimputil.h> #include <bdldfp_decimalimputil_inteldfp.h> #include <bdldfp_intelimpwrapper.h> #include <bsls_assert.h> #include <bsl_cstring.h> namespace BloombergLP { namespace bdldfp { // ================================= // class DecimalConvertUtil_IntelDfp // ================================= struct DecimalConvertUtil_IntelDfp { // This 'struct' provides a namespace for utility functions that convert // between the decimal floating-point types of 'bdldfp_decimal' and various // other formats. // Convert to Binary Floating-Point from C++ Decimal TR // CLASS METHODS // decimalToDouble functions static double decimal32ToDouble (Decimal32 decimal); static double decimal64ToDouble (Decimal64 decimal); static double decimal128ToDouble(Decimal128 decimal); static double decimalToDouble (Decimal32 decimal); static double decimalToDouble (Decimal64 decimal); static double decimalToDouble (Decimal128 decimal); // Return a 'double' object having the value closest to the value of // the specified 'decimal' object following the conversion rules // defined by IEEE-754: // //: o If the 'decimal' object is a NaN, return a NaN. //: //: o Otherwise if 'decimal' is positive or negative infinity, return //: infinity of the same sign. //: //: o Otherwise if 'decimal' is positive or negative zero, return zero //: of the same sign. //: //: o Otherwise if 'decimal' object has an absolute value that is //: larger than 'std::numeric_limits<double>::max()', raise the //: "overflow" floating-point exception and return infinity of the //: same sign as 'decimal'. //: //: o Otherwise if 'decimal' has an absolute value that is smaller than //: 'std::numeric_limits<double>::min()', raise the "underflow" //: floating-point exception and return zero of the same sign as //: 'decimal'. //: //: o Otherwise if 'decimal' has a value that has more significant //: base-10 digits than 'std::numeric_limits<double>::digits10', //: raise the "inexact" floating-point exception, round that value //: according to the *binary* rounding direction setting of the //: floating-point environment, and return the result of that. //: //: o Otherwise if 'decimal' has a significand that cannot be exactly //: represented using binary floating-point, raise the "inexact" //: floating-point exception, roundthat value according to the //: *binary* rounding direction setting of the environment, and //: return the result of that. //: //: o Otherwise use the exact value of the 'other' object for the //: initialization if this object. // decimalToFloat functions static float decimal32ToFloat (Decimal32 decimal); static float decimal64ToFloat (Decimal64 decimal); static float decimal128ToFloat(Decimal128 decimal); static float decimalToFloat (Decimal32 decimal); static float decimalToFloat (Decimal64 decimal); static float decimalToFloat (Decimal128 decimal); // Return a 'float' object having the value closest to the value of the // specified 'decimal' object following the conversion rules defined // by IEEE-754: // //: o If the 'decimal' object is a NaN, return a NaN. //: //: o Otherwise if 'decimal' is positive or negative infinity, return //: infinity of the same sign. //: //: o Otherwise if 'decimal' is positive or negative zero, return zero //: of the same sign. //: //: o Otherwise if 'decimal' object has an absolute value that is //: larger than 'std::numeric_limits<long double>::max()', raise the //: "overflow" floating-point exception and return infinity of the //: same sign as 'decimal'. //: //: o Otherwise if 'decimal' has an absolute value that is smaller than //: 'std::numeric_limits<float>::min()', raise the "underflow" //: floating-point exception and return zero of the same sign as //: 'decimal'. //: //: o Otherwise if 'decimal' has a value that has more significant //: base-10 digits than 'std::numeric_limits<float>::digits10', //: raise the "inexact" floating-point exception, round that value //: according to the *binary* rounding direction setting of the //: floating-point environment, and return the result of that. //: //: o Otherwise if 'decimal' has a significand that cannot be exactly //: represented using binary floating-point, raise the "inexact" //: floating-point exception, roundthat value according to the //: *binary* rounding direction setting of the environment, and //: return the result of that. //: //: o Otherwise use the exact value of the 'other' object for the //: initialization if this object. // decimalToDPD functions static void decimal32ToDPD( unsigned char *buffer, Decimal32 decimal); static void decimal64ToDPD( unsigned char *buffer, Decimal64 decimal); static void decimal128ToDPD(unsigned char *buffer, Decimal128 decimal); static void decimalToDPD( unsigned char *buffer, Decimal32 decimal); static void decimalToDPD( unsigned char *buffer, Decimal64 decimal); static void decimalToDPD( unsigned char *buffer, Decimal128 decimal); // Populate the specified 'buffer' with the Densely Packed Decimal // (DPD) representation of the specified 'decimal' value. The DPD // representations of 'Decimal32', 'Decimal64', and 'Decimal128' // require 4, 8, and 16 bytes respectively. The behavior is undefined // unless 'buffer' points to a contiguous sequence of at least // 'sizeof(decimal)' bytes. Note that the DPD representation is // defined in section 3.5 of IEEE 754-2008. // decimalFromDPD functions static Decimal32 decimal32FromDPD( const unsigned char *buffer); static Decimal64 decimal64FromDPD( const unsigned char *buffer); static Decimal128 decimal128FromDPD(const unsigned char *buffer); // Return the native implementation representation of the value of the // same size base-10 floating-point value stored in Densely Packed // Decimal format at the specified 'buffer' address. The behavior is // undefined unless 'buffer' points to a memory area at least // 'sizeof(decimal)' in size containing a value in DPD format. static void decimalFromDPD(Decimal32 *decimal, const unsigned char *buffer); static void decimalFromDPD(Decimal64 *decimal, const unsigned char *buffer); static void decimalFromDPD(Decimal128 *decimal, const unsigned char *buffer); // Store, into the specified 'decimal', the native implementation // representation of the value of the same size base-10 floating point // value represented in Densely Packed Decimal format, at the specified // 'buffer' address. The behavior is undefined unless 'buffer' points // to a memory area at least 'sizeof(decimal)' in size containing a // value in DPD format. // decimalToBID functions static void decimal32ToBID( unsigned char *buffer, Decimal32 decimal); static void decimal64ToBID( unsigned char *buffer, Decimal64 decimal); static void decimal128ToBID(unsigned char *buffer, Decimal128 decimal); static void decimalToBID( unsigned char *buffer, Decimal32 decimal); static void decimalToBID( unsigned char *buffer, Decimal64 decimal); static void decimalToBID( unsigned char *buffer, Decimal128 decimal); // Populate the specified 'buffer' with the Binary Integer Decimal // (BID) representation of the specified 'decimal' value. The BID // representations of 'Decimal32', 'Decimal64', and 'Decimal128' // require 4, 8, and 16 bytes respectively. The behavior is undefined // unless 'buffer' points to a contiguous sequence of at least // 'sizeof(decimal)' bytes. Note that the BID representation is // defined in section 3.5 of IEEE 754-2008. // decimalFromBID functions static Decimal32 decimal32FromBID( const unsigned char *buffer); static Decimal64 decimal64FromBID( const unsigned char *buffer); static Decimal128 decimal128FromBID(const unsigned char *buffer); // Return the native implementation representation of the value of the // same size base-10 floating-point value stored in Binary Integer // Decimal format at the specified 'buffer' address. The behavior is // undefined unless 'buffer' points to a memory area at least // 'sizeof(decimal)' in size containing a value in BID format. static void decimalFromBID(Decimal32 *decimal, const unsigned char *buffer); static void decimalFromBID(Decimal64 *decimal, const unsigned char *buffer); static void decimalFromBID(Decimal128 *decimal, const unsigned char *buffer); // Store, into the specified 'decimal', the native implementation // representation of the value of the same size base-10 floating point // value represented in Binary Integer Decimal format, at the specified // 'buffer' address. The behavior is undefined unless 'buffer' points // to a memory area at least 'sizeof(decimal)' in size containing a // value in BID format. }; // ============================================================================ // INLINE FUNCTION DEFINITIONS // ============================================================================ // decimalToDouble functions inline double DecimalConvertUtil_IntelDfp::decimal32ToDouble(Decimal32 decimal) { return decimalToDouble(decimal); } inline double DecimalConvertUtil_IntelDfp::decimal64ToDouble(Decimal64 decimal) { return decimalToDouble(decimal); } inline double DecimalConvertUtil_IntelDfp::decimal128ToDouble(Decimal128 decimal) { return decimalToDouble(decimal); } inline double DecimalConvertUtil_IntelDfp::decimalToDouble(Decimal32 decimal) { _IDEC_flags flags; return __bid32_to_binary64(decimal.data()->d_raw, &flags); } inline double DecimalConvertUtil_IntelDfp::decimalToDouble(Decimal64 decimal) { _IDEC_flags flags; return __bid64_to_binary64(decimal.data()->d_raw, &flags); } inline double DecimalConvertUtil_IntelDfp::decimalToDouble(Decimal128 decimal) { _IDEC_flags flags; return __bid128_to_binary64(decimal.data()->d_raw, &flags); } // decimalToFloat functions inline float DecimalConvertUtil_IntelDfp::decimal32ToFloat(Decimal32 decimal) { return decimalToFloat(decimal); } inline float DecimalConvertUtil_IntelDfp::decimal64ToFloat(Decimal64 decimal) { return decimalToFloat(decimal); } inline float DecimalConvertUtil_IntelDfp::decimal128ToFloat(Decimal128 decimal) { return decimalToFloat(decimal); } inline float DecimalConvertUtil_IntelDfp::decimalToFloat(Decimal32 decimal) { _IDEC_flags flags; return __bid32_to_binary32(decimal.data()->d_raw, &flags); } inline float DecimalConvertUtil_IntelDfp::decimalToFloat(Decimal64 decimal) { _IDEC_flags flags; return __bid64_to_binary32(decimal.data()->d_raw, &flags); } inline float DecimalConvertUtil_IntelDfp::decimalToFloat(Decimal128 decimal) { _IDEC_flags flags; return __bid128_to_binary32(decimal.data()->d_raw, &flags); } // decimalToDPD functions inline void DecimalConvertUtil_IntelDfp::decimal32ToDPD(unsigned char *buffer, Decimal32 decimal) { decimalToDPD(buffer, decimal); } inline void DecimalConvertUtil_IntelDfp::decimal64ToDPD(unsigned char *buffer, Decimal64 decimal) { decimalToDPD(buffer, decimal); } inline void DecimalConvertUtil_IntelDfp::decimal128ToDPD(unsigned char *buffer, Decimal128 decimal) { decimalToDPD(buffer, decimal); } inline void DecimalConvertUtil_IntelDfp::decimalToDPD(unsigned char *buffer, Decimal32 decimal) { decimal.data()->d_raw = __bid_to_dpd32(decimal.data()->d_raw); bsl::memcpy(buffer, &decimal, sizeof(decimal)); } inline void DecimalConvertUtil_IntelDfp::decimalToDPD(unsigned char *buffer, Decimal64 decimal) { decimal.data()->d_raw = __bid_to_dpd64(decimal.data()->d_raw); bsl::memcpy(buffer, &decimal, sizeof(decimal)); } inline void DecimalConvertUtil_IntelDfp::decimalToDPD(unsigned char *buffer, Decimal128 decimal) { decimal.data()->d_raw = __bid_to_dpd128(decimal.data()->d_raw); bsl::memcpy(buffer, &decimal, sizeof(decimal)); } // decimalFromDPD functions inline Decimal32 DecimalConvertUtil_IntelDfp::decimal32FromDPD( const unsigned char *buffer) { BSLS_ASSERT(buffer); DecimalImpUtil::ValueType32 value; bsl::memcpy(&value, buffer, sizeof(value)); value.d_raw = __bid_dpd_to_bid32(value.d_raw); return Decimal32(value); } inline Decimal64 DecimalConvertUtil_IntelDfp::decimal64FromDPD( const unsigned char *buffer) { BSLS_ASSERT(buffer); DecimalImpUtil::ValueType64 value; bsl::memcpy(&value, buffer, sizeof(value)); value.d_raw = __bid_dpd_to_bid64(value.d_raw); return Decimal64(value); } inline Decimal128 DecimalConvertUtil_IntelDfp::decimal128FromDPD( const unsigned char *buffer) { BSLS_ASSERT(buffer); DecimalImpUtil::ValueType128 value; bsl::memcpy(&value, buffer, sizeof(value)); value.d_raw = __bid_dpd_to_bid128(value.d_raw); return Decimal128(value); } inline void DecimalConvertUtil_IntelDfp::decimalFromDPD(Decimal32 *decimal, const unsigned char *buffer) { BSLS_ASSERT(decimal); BSLS_ASSERT(buffer); *decimal = decimal32FromDPD(buffer); } inline void DecimalConvertUtil_IntelDfp::decimalFromDPD(Decimal64 *decimal, const unsigned char *buffer) { BSLS_ASSERT(decimal); BSLS_ASSERT(buffer); *decimal = decimal64FromDPD(buffer); } inline void DecimalConvertUtil_IntelDfp::decimalFromDPD(Decimal128 *decimal, const unsigned char *buffer) { BSLS_ASSERT(decimal); BSLS_ASSERT(buffer); *decimal = decimal128FromDPD(buffer); } // decimalToBID functions inline void DecimalConvertUtil_IntelDfp::decimal32ToBID(unsigned char *buffer, Decimal32 decimal) { decimalToBID(buffer, decimal); } inline void DecimalConvertUtil_IntelDfp::decimal64ToBID(unsigned char *buffer, Decimal64 decimal) { decimalToBID(buffer, decimal); } inline void DecimalConvertUtil_IntelDfp::decimal128ToBID(unsigned char *buffer, Decimal128 decimal) { decimalToBID(buffer, decimal); } inline void DecimalConvertUtil_IntelDfp::decimalToBID(unsigned char *buffer, Decimal32 decimal) { bsl::memcpy(buffer, &decimal, sizeof(decimal)); } inline void DecimalConvertUtil_IntelDfp::decimalToBID(unsigned char *buffer, Decimal64 decimal) { bsl::memcpy(buffer, &decimal, sizeof(decimal)); } inline void DecimalConvertUtil_IntelDfp::decimalToBID(unsigned char *buffer, Decimal128 decimal) { bsl::memcpy(buffer, &decimal, sizeof(decimal)); } // decimalFromBID functions inline Decimal32 DecimalConvertUtil_IntelDfp::decimal32FromBID( const unsigned char *buffer) { BSLS_ASSERT(buffer); DecimalImpUtil::ValueType32 value; bsl::memcpy(&value, buffer, sizeof(value)); return Decimal32(value); } inline Decimal64 DecimalConvertUtil_IntelDfp::decimal64FromBID( const unsigned char *buffer) { BSLS_ASSERT(buffer); DecimalImpUtil::ValueType64 value; bsl::memcpy(&value, buffer, sizeof(value)); return Decimal64(value); } inline Decimal128 DecimalConvertUtil_IntelDfp::decimal128FromBID( const unsigned char *buffer) { BSLS_ASSERT(buffer); DecimalImpUtil::ValueType128 value; bsl::memcpy(&value, buffer, sizeof(value)); return Decimal128(value); } inline void DecimalConvertUtil_IntelDfp::decimalFromBID(Decimal32 *decimal, const unsigned char *buffer) { BSLS_ASSERT(decimal); BSLS_ASSERT(buffer); *decimal = decimal32FromBID(buffer); } inline void DecimalConvertUtil_IntelDfp::decimalFromBID(Decimal64 *decimal, const unsigned char *buffer) { BSLS_ASSERT(decimal); BSLS_ASSERT(buffer); *decimal = decimal64FromBID(buffer); } inline void DecimalConvertUtil_IntelDfp::decimalFromBID(Decimal128 *decimal, const unsigned char *buffer) { BSLS_ASSERT(decimal); BSLS_ASSERT(buffer); *decimal = decimal128FromBID(buffer); } } // close package namespace } // close enterprise namespace #endif #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 ----------------------------------