From 178be69bc4df26147a49b3f97216506db746eda9 Mon Sep 17 00:00:00 2001 From: Roman Nozdrin Date: Mon, 16 Nov 2020 11:15:57 +0000 Subject: [PATCH] MCOL-4394 __float128 related code had been moved into a separate file Trim to double and to long double conversions for Decimal --- datatypes/mcs_decimal.h | 60 ++++++++++----------- datatypes/mcs_float128.h | 87 +++++++++++++++++++++++++++++++ datatypes/mcs_int128.cpp | 12 ----- datatypes/mcs_int128.h | 61 +++++++++++----------- dbcon/execplan/treenode.h | 2 +- utils/funcexp/func_cast.cpp | 6 ++- utils/funcexp/func_ceil.cpp | 4 +- utils/funcexp/func_floor.cpp | 4 +- utils/funcexp/func_mod.cpp | 8 +-- utils/funcexp/func_round.cpp | 4 +- utils/funcexp/func_truncate.cpp | 4 +- utils/rowgroup/rowaggregation.cpp | 5 +- 12 files changed, 168 insertions(+), 89 deletions(-) create mode 100644 datatypes/mcs_float128.h diff --git a/datatypes/mcs_decimal.h b/datatypes/mcs_decimal.h index 387c4f662..67867f944 100644 --- a/datatypes/mcs_decimal.h +++ b/datatypes/mcs_decimal.h @@ -25,6 +25,7 @@ #include "exceptclasses.h" #include "widedecimalutils.h" #include "mcs_int128.h" +#include "mcs_float128.h" namespace datatypes @@ -334,36 +335,6 @@ class Decimal return static_cast(value); } - /** - @brief The method converts a wide decimal value to a double. - */ - static inline double getDoubleFromWideDecimal(const int128_t& value, int8_t scale) - { - int128_t scaleDivisor; - - getScaleDivisor(scaleDivisor, scale); - - __float128 tmpval = (__float128) value / scaleDivisor; - - return getDoubleFromFloat128(tmpval); - } - - /** - @brief The method converts a wide decimal value to a double. - */ - static inline double getDoubleFromWideDecimal(const int128_t& value) - { - return getDoubleFromFloat128(static_cast<__float128>(value)); - } - - /** - @brief The method converts a wide decimal value to a long double. - */ - static inline long double getLongDoubleFromWideDecimal(const int128_t& value) - { - return getLongDoubleFromFloat128(static_cast<__float128>(value)); - } - /** @brief The method converts a wide decimal value to an int64_t, saturating the value if necessary. @@ -598,6 +569,35 @@ class VDecimal: public TSInt128 return ret; } + inline TSInt128 toTSInt128() const + { + return TSInt128(s128Value); + } + + inline TFloat128 toTFloat128() const + { + return TFloat128(s128Value); + } + + inline double toDouble() const + { + int128_t scaleDivisor; + getScaleDivisor(scaleDivisor, scale); + datatypes::TFloat128 tmpval((__float128) s128Value / scaleDivisor); + return static_cast(tmpval); + } + + inline operator double() const + { + return toDouble(); + } + + inline long double toLongDouble() const + { + datatypes::TFloat128 y(s128Value); + return static_cast(y); + } + bool operator==(const VDecimal& rhs) const { if (precision > datatypes::INT64MAXPRECISION && diff --git a/datatypes/mcs_float128.h b/datatypes/mcs_float128.h new file mode 100644 index 000000000..825858804 --- /dev/null +++ b/datatypes/mcs_float128.h @@ -0,0 +1,87 @@ +/* + Copyright (C) 2020 MariaDB Corporation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. +*/ +#ifndef MCS_TSFLOAT128_H_INCLUDED +#define MCS_TSFLOAT128_H_INCLUDED + +#include +#include + +namespace datatypes +{ + +//class TSInt128; +using int128_t = __int128; + +class TFloat128 +{ + public: + static constexpr uint16_t MAXLENGTH16BYTES = 42; + // A variety of ctors for aligned and unaligned arguments + TFloat128(): value(0) { } + + // aligned argument + TFloat128(const __float128& x) { value = x; } + TFloat128(const int128_t& x) { value = static_cast<__float128>(x); } + + // Method returns max length of a string representation + static constexpr uint8_t maxLength() + { + return TFloat128::MAXLENGTH16BYTES; + } + + // The method converts a TFloat128 to integral types + inline operator double() const + { + return toDouble(); + } + + inline double toDouble() const + { + if (value > static_cast<__float128>(DBL_MAX)) + return DBL_MAX; + else if (value < -static_cast<__float128>(DBL_MAX)) + return -DBL_MAX; + + return static_cast(value); + } + + inline operator long double() const + { + return toLongDouble(); + } + + + inline long double toLongDouble() const + { + if (value > static_cast<__float128>(LDBL_MAX)) + return LDBL_MAX; + else if (value < -static_cast<__float128>(LDBL_MAX)) + return -LDBL_MAX; + + return static_cast(value); + } + private: + __float128 value; +}; + +} //end of namespace + +#endif // MCS_TSFLOAT128_H_INCLUDED +// vim:ts=2 sw=2: + diff --git a/datatypes/mcs_int128.cpp b/datatypes/mcs_int128.cpp index d94f5f1bb..0c488c40f 100644 --- a/datatypes/mcs_int128.cpp +++ b/datatypes/mcs_int128.cpp @@ -24,18 +24,6 @@ namespace datatypes { - // The method converts a wide decimal s128Value to a double. - inline double TSInt128::getDoubleFromWideDecimal() - { - return getDoubleFromFloat128(static_cast<__float128>(s128Value)); - } - - // The method converts a wide decimal s128Value to a long double. - inline long double TSInt128::getLongDoubleFromWideDecimal() - { - return getLongDoubleFromFloat128(static_cast<__float128>(s128Value)); - } - uint8_t TSInt128::printPodParts(char* buf, const int128_t& high, const int128_t& mid, diff --git a/datatypes/mcs_int128.h b/datatypes/mcs_int128.h index 3d508420a..e923b2e1c 100644 --- a/datatypes/mcs_int128.h +++ b/datatypes/mcs_int128.h @@ -24,6 +24,7 @@ #include #include #include +#include "mcs_float128.h" // Inline asm has three argument lists: output, input and clobber list #if defined(__GNUC__) && (__GNUC___ > 7) @@ -111,30 +112,6 @@ struct is_uint128_t { static const bool value = true; }; -// The method converts a __float128 s128Value to a double. -static inline double getDoubleFromFloat128(const __float128& value) -{ - if (value > static_cast<__float128>(DBL_MAX)) - return DBL_MAX; - else if (value < -static_cast<__float128>(DBL_MAX)) - return -DBL_MAX; - - return static_cast(value); -} - - -// The method converts a __float128 value to a long double. -static inline long double getLongDoubleFromFloat128(const __float128& value) -{ - if (value > static_cast<__float128>(LDBL_MAX)) - return LDBL_MAX; - else if (value < -static_cast<__float128>(LDBL_MAX)) - return -LDBL_MAX; - - return static_cast(value); -} - - class TSInt128 { public: @@ -203,6 +180,36 @@ class TSInt128 return s128Value == static_cast(x); } + inline operator double() const + { + return toDouble(); + } + + inline long double toDouble() const + { + return static_cast(s128Value); + } + + inline operator long double() const + { + return toLongDouble(); + } + + inline long double toLongDouble() const + { + return static_cast(s128Value); + } + + inline operator TFloat128() const + { + return toTFloat128(); + } + + inline TFloat128 toTFloat128() const + { + return TFloat128(s128Value); + } + // print int128_t parts represented as PODs uint8_t printPodParts(char* buf, const int128_t& high, @@ -219,12 +226,6 @@ class TSInt128 friend std::ostream& operator<<(std::ostream& os, const TSInt128& x); - // The method converts a wide decimal s128Value to a double. - inline double getDoubleFromWideDecimal(); - - // The method converts a wide decimal s128Value to a long double. - inline long double getLongDoubleFromWideDecimal(); - // The method converts a wide decimal s128Value to an int64_t, // saturating the s128Value if necessary. inline int64_t getInt64FromWideDecimal(); diff --git a/dbcon/execplan/treenode.h b/dbcon/execplan/treenode.h index 3d94a6e09..e52f986a5 100644 --- a/dbcon/execplan/treenode.h +++ b/dbcon/execplan/treenode.h @@ -927,7 +927,7 @@ inline double TreeNode::getDoubleVal() { if (fResultType.colWidth == datatypes::MAXDECIMALWIDTH) { - return datatypes::Decimal::getDoubleFromWideDecimal(fResult.decimalVal.s128Value, fResult.decimalVal.scale); + return static_cast(fResult.decimalVal); } else { diff --git a/utils/funcexp/func_cast.cpp b/utils/funcexp/func_cast.cpp index ef36bb320..eff0e69ae 100644 --- a/utils/funcexp/func_cast.cpp +++ b/utils/funcexp/func_cast.cpp @@ -1881,9 +1881,11 @@ double Func_cast_decimal::getDoubleVal(Row& row, isNull, operationColType); + // WIP MCOL-641 This could deliver wrong result b/c wide DECIMAL might have + // p <= INT64MAXPRECISION if (decimal.precision > datatypes::INT64MAXPRECISION) { - return datatypes::Decimal::getDoubleFromWideDecimal(decimal.s128Value, decimal.scale); + return static_cast(decimal); } return (double) decimal.value / helpers::powerOf10_c[decimal.scale]; @@ -1994,7 +1996,7 @@ double Func_cast_double::getDoubleVal(Row& row, if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) { - dblval = datatypes::Decimal::getDoubleFromWideDecimal(decimal.s128Value, decimal.scale); + dblval = static_cast(decimal); } else { diff --git a/utils/funcexp/func_ceil.cpp b/utils/funcexp/func_ceil.cpp index de374af85..687f50c85 100644 --- a/utils/funcexp/func_ceil.cpp +++ b/utils/funcexp/func_ceil.cpp @@ -392,7 +392,7 @@ double Func_ceil::getDoubleVal(Row& row, if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) { - ret = datatypes::Decimal::getDoubleFromWideDecimal(tmp.s128Value); + ret = static_cast(tmp.toTSInt128()); } else { @@ -448,7 +448,7 @@ long double Func_ceil::getLongDoubleVal(Row& row, if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) { - ret = datatypes::Decimal::getLongDoubleFromWideDecimal(tmp.s128Value); + ret = static_cast(tmp.toTSInt128()); } else { diff --git a/utils/funcexp/func_floor.cpp b/utils/funcexp/func_floor.cpp index 3252fa031..8e87be745 100644 --- a/utils/funcexp/func_floor.cpp +++ b/utils/funcexp/func_floor.cpp @@ -330,7 +330,7 @@ double Func_floor::getDoubleVal(Row& row, if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) { - ret = datatypes::Decimal::getDoubleFromWideDecimal(tmp.s128Value); + ret = static_cast(tmp.toTSInt128()); } else { @@ -377,7 +377,7 @@ long double Func_floor::getLongDoubleVal(Row& row, if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) { - ret = datatypes::Decimal::getLongDoubleFromWideDecimal(tmp.s128Value); + ret = static_cast(tmp.toTSInt128()); } else { diff --git a/utils/funcexp/func_mod.cpp b/utils/funcexp/func_mod.cpp index 01432cea8..a2f6efcbe 100644 --- a/utils/funcexp/func_mod.cpp +++ b/utils/funcexp/func_mod.cpp @@ -241,8 +241,8 @@ double Func_mod::getDoubleVal(Row& row, datatypes::getScaleDivisor(scaleDivisor, d.scale); int128_t value = d.s128Value / scaleDivisor; int128_t lefto = d.s128Value % scaleDivisor; - __float128 tmp = (__float128) (value % div) + (__float128) lefto / scaleDivisor; - mod = datatypes::getDoubleFromFloat128(tmp); + datatypes::TFloat128 tmp((__float128) (value % div) + (__float128) lefto / scaleDivisor); + mod = static_cast(tmp); } } else @@ -364,8 +364,8 @@ long double Func_mod::getLongDoubleVal(Row& row, datatypes::getScaleDivisor(scaleDivisor, d.scale); int128_t value = d.s128Value / scaleDivisor; int128_t lefto = d.s128Value % scaleDivisor; - __float128 tmp = (__float128) (value % div) + (__float128) lefto / scaleDivisor; - mod = datatypes::getLongDoubleFromFloat128(tmp); + datatypes::TFloat128 tmp((__float128) (value % div) + (__float128) lefto / scaleDivisor); + mod = static_cast(tmp); } } else diff --git a/utils/funcexp/func_round.cpp b/utils/funcexp/func_round.cpp index b034cf3b3..6a1374475 100644 --- a/utils/funcexp/func_round.cpp +++ b/utils/funcexp/func_round.cpp @@ -210,7 +210,7 @@ double Func_round::getDoubleVal(Row& row, if (!op_ct.isWideDecimalType()) d = x.value; else - d = datatypes::Decimal::getDoubleFromWideDecimal(x.s128Value); + d = static_cast(x.toTSInt128()); if (x.scale > 0) { @@ -277,7 +277,7 @@ long double Func_round::getLongDoubleVal(Row& row, if (!op_ct.isWideDecimalType()) d = x.value; else - d = datatypes::Decimal::getDoubleFromWideDecimal(x.s128Value); + d = static_cast(x.toTSInt128()); if (x.scale > 0) { diff --git a/utils/funcexp/func_truncate.cpp b/utils/funcexp/func_truncate.cpp index 02455de61..dc59cc578 100644 --- a/utils/funcexp/func_truncate.cpp +++ b/utils/funcexp/func_truncate.cpp @@ -233,7 +233,7 @@ double Func_truncate::getDoubleVal(Row& row, if (!op_ct.isWideDecimalType()) d = x.value; else - d = datatypes::Decimal::getDoubleFromWideDecimal(x.s128Value); + d = static_cast(x.toTSInt128()); if (x.scale > 0) { @@ -293,7 +293,7 @@ long double Func_truncate::getLongDoubleVal(Row& row, if (!op_ct.isWideDecimalType()) d = x.value; else - d = datatypes::Decimal::getDoubleFromWideDecimal(x.s128Value); + d = static_cast(x.toTSInt128()); if (x.scale > 0) { diff --git a/utils/rowgroup/rowaggregation.cpp b/utils/rowgroup/rowaggregation.cpp index 05c30f6cb..f8e3cde03 100755 --- a/utils/rowgroup/rowaggregation.cpp +++ b/utils/rowgroup/rowaggregation.cpp @@ -2045,8 +2045,9 @@ void RowAggregation::doStatistics(const Row& rowIn, int64_t colIn, int64_t colOu case execplan::CalpontSystemCatalog::UDECIMAL: // handle scale later if (LIKELY(fRowGroupIn.getColumnWidth(colIn) == datatypes::MAXDECIMALWIDTH)) { - int128_t* val128InPtr = rowIn.getBinaryField(colIn); - valIn = Dec::getLongDoubleFromWideDecimal(*val128InPtr); + // To save from unaligned memory + datatypes::TSInt128 val128In(rowIn.getBinaryField(colIn)); + valIn = static_cast(val128In.toTFloat128()); } else if (fRowGroupIn.getColumnWidth(colIn) <= datatypes::MAXLEGACYWIDTH) {