Make Field::getScaleMultiplier() inline to allow using FieldVisitorConvertToNumber

in the "clickhouse_parsers" library.
This commit is contained in:
Vitaly Baranov 2019-11-16 16:54:56 +03:00
parent 3e6619c076
commit 8035af3a79
8 changed files with 32 additions and 59 deletions

View File

@ -3,11 +3,18 @@
#include <cstdint>
#include <limits>
#include <Core/Defines.h>
// Also defined in Core/Defines.h
#if !defined(NO_SANITIZE_UNDEFINED)
#if defined(__clang__)
#define NO_SANITIZE_UNDEFINED __attribute__((__no_sanitize__("undefined")))
#else
#define NO_SANITIZE_UNDEFINED
#endif
#endif
/// On overlow, the function returns unspecified value.
inline NO_SANITIZE_UNDEFINED uint64_t intExp2(int x)
{
return 1ULL << x;

View File

@ -88,9 +88,9 @@ public:
Shift shift;
if (scale_a < scale_b)
shift.a = DataTypeDecimal<B>(maxDecimalPrecision<B>(), scale_b).getScaleMultiplier(scale_b - scale_a);
shift.a = B::getScaleMultiplier(scale_b - scale_a);
if (scale_a > scale_b)
shift.b = DataTypeDecimal<A>(maxDecimalPrecision<A>(), scale_a).getScaleMultiplier(scale_a - scale_b);
shift.b = A::getScaleMultiplier(scale_a - scale_b);
return applyWithScale(a, b, shift);
}

View File

@ -300,21 +300,6 @@ namespace DB
}
template <> Decimal32 DecimalField<Decimal32>::getScaleMultiplier() const
{
return DataTypeDecimal<Decimal32>::getScaleMultiplier(scale);
}
template <> Decimal64 DecimalField<Decimal64>::getScaleMultiplier() const
{
return DataTypeDecimal<Decimal64>::getScaleMultiplier(scale);
}
template <> Decimal128 DecimalField<Decimal128>::getScaleMultiplier() const
{
return DataTypeDecimal<Decimal128>::getScaleMultiplier(scale);
}
template <typename T>
static bool decEqual(T x, T y, UInt32 x_scale, UInt32 y_scale)
{

View File

@ -102,7 +102,7 @@ public:
operator T() const { return dec; }
T getValue() const { return dec; }
T getScaleMultiplier() const;
T getScaleMultiplier() const { return T::getScaleMultiplier(scale); }
UInt32 getScale() const { return scale; }
template <typename U>

View File

@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include <common/Types.h>
#include <Common/intExp.h>
namespace DB
@ -145,6 +146,8 @@ struct Decimal
const Decimal<T> & operator /= (const T & x) { value /= x; return *this; }
const Decimal<T> & operator %= (const T & x) { value %= x; return *this; }
static T getScaleMultiplier(UInt32 scale);
T value;
};
@ -170,6 +173,10 @@ template <> struct NativeType<Decimal32> { using Type = Int32; };
template <> struct NativeType<Decimal64> { using Type = Int64; };
template <> struct NativeType<Decimal128> { using Type = Int128; };
template <> inline Int32 Decimal32::getScaleMultiplier(UInt32 scale) { return common::exp10_i32(scale); }
template <> inline Int64 Decimal64::getScaleMultiplier(UInt32 scale) { return common::exp10_i64(scale); }
template <> inline Int128 Decimal128::getScaleMultiplier(UInt32 scale) { return common::exp10_i128(scale); }
inline const char * getTypeName(TypeIndex idx)
{
switch (idx)

View File

@ -58,7 +58,7 @@ bool DataTypeDecimal<T>::tryReadText(T & x, ReadBuffer & istr, UInt32 precision,
{
UInt32 unread_scale = scale;
bool done = tryReadDecimalText(istr, x, precision, unread_scale);
x *= getScaleMultiplier(unread_scale);
x *= T::getScaleMultiplier(unread_scale);
return done;
}
@ -70,7 +70,7 @@ void DataTypeDecimal<T>::readText(T & x, ReadBuffer & istr, UInt32 precision, UI
readCSVDecimalText(istr, x, precision, unread_scale);
else
readDecimalText(istr, x, precision, unread_scale);
x *= getScaleMultiplier(unread_scale);
x *= T::getScaleMultiplier(unread_scale);
}
template <typename T>
@ -96,7 +96,7 @@ T DataTypeDecimal<T>::parseFromString(const String & str) const
T x;
UInt32 unread_scale = scale;
readDecimalText(buf, x, precision, unread_scale, true);
x *= getScaleMultiplier(unread_scale);
x *= T::getScaleMultiplier(unread_scale);
return x;
}
@ -271,25 +271,6 @@ void registerDataTypeDecimal(DataTypeFactory & factory)
}
template <>
Decimal32 DataTypeDecimal<Decimal32>::getScaleMultiplier(UInt32 scale_)
{
return decimalScaleMultiplier<Int32>(scale_);
}
template <>
Decimal64 DataTypeDecimal<Decimal64>::getScaleMultiplier(UInt32 scale_)
{
return decimalScaleMultiplier<Int64>(scale_);
}
template <>
Decimal128 DataTypeDecimal<Decimal128>::getScaleMultiplier(UInt32 scale_)
{
return decimalScaleMultiplier<Int128>(scale_);
}
/// Explicit template instantiations.
template class DataTypeDecimal<Decimal32>;
template class DataTypeDecimal<Decimal64>;

View File

@ -130,7 +130,7 @@ public:
UInt32 getPrecision() const { return precision; }
UInt32 getScale() const { return scale; }
T getScaleMultiplier() const { return getScaleMultiplier(scale); }
T getScaleMultiplier() const { return T::getScaleMultiplier(scale); }
T wholePart(T x) const
{
@ -148,7 +148,7 @@ public:
return x % getScaleMultiplier();
}
T maxWholeValue() const { return getScaleMultiplier(maxPrecision() - scale) - T(1); }
T maxWholeValue() const { return T::getScaleMultiplier(maxPrecision() - scale) - T(1); }
bool canStoreWhole(T x) const
{
@ -165,7 +165,7 @@ public:
if (getScale() < x.getScale())
throw Exception("Decimal result's scale is less then argiment's one", ErrorCodes::ARGUMENT_OUT_OF_BOUND);
UInt32 scale_delta = getScale() - x.getScale(); /// scale_delta >= 0
return getScaleMultiplier(scale_delta);
return T::getScaleMultiplier(scale_delta);
}
template <typename U>
@ -181,7 +181,6 @@ public:
void readText(T & x, ReadBuffer & istr, bool csv = false) const { readText(x, istr, precision, scale, csv); }
static void readText(T & x, ReadBuffer & istr, UInt32 precision, UInt32 scale, bool csv = false);
static bool tryReadText(T & x, ReadBuffer & istr, UInt32 precision, UInt32 scale);
static T getScaleMultiplier(UInt32 scale);
private:
const UInt32 precision;
@ -264,12 +263,12 @@ convertDecimals(const typename FromDataType::FieldType & value, UInt32 scale_fro
MaxNativeType converted_value;
if (scale_to > scale_from)
{
converted_value = DataTypeDecimal<MaxFieldType>::getScaleMultiplier(scale_to - scale_from);
converted_value = MaxFieldType::getScaleMultiplier(scale_to - scale_from);
if (common::mulOverflow(static_cast<MaxNativeType>(value), converted_value, converted_value))
throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
}
else
converted_value = value / DataTypeDecimal<MaxFieldType>::getScaleMultiplier(scale_from - scale_to);
converted_value = value / MaxFieldType::getScaleMultiplier(scale_from - scale_to);
if constexpr (sizeof(FromFieldType) > sizeof(ToFieldType))
{
@ -289,7 +288,7 @@ convertFromDecimal(const typename FromDataType::FieldType & value, UInt32 scale)
using ToFieldType = typename ToDataType::FieldType;
if constexpr (std::is_floating_point_v<ToFieldType>)
return static_cast<ToFieldType>(value) / FromDataType::getScaleMultiplier(scale);
return static_cast<ToFieldType>(value) / FromFieldType::getScaleMultiplier(scale);
else
{
FromFieldType converted_value = convertDecimals<FromDataType, FromDataType>(value, scale, 0);
@ -320,14 +319,15 @@ inline std::enable_if_t<IsDataTypeNumber<FromDataType> && IsDataTypeDecimal<ToDa
convertToDecimal(const typename FromDataType::FieldType & value, UInt32 scale)
{
using FromFieldType = typename FromDataType::FieldType;
using ToNativeType = typename ToDataType::FieldType::NativeType;
using ToFieldType = typename ToDataType::FieldType;
using ToNativeType = typename ToFieldType::NativeType;
if constexpr (std::is_floating_point_v<FromFieldType>)
{
if (!std::isfinite(value))
throw Exception("Decimal convert overflow. Cannot convert infinity or NaN to decimal", ErrorCodes::DECIMAL_OVERFLOW);
auto out = value * ToDataType::getScaleMultiplier(scale);
auto out = value * ToFieldType::getScaleMultiplier(scale);
if constexpr (std::is_same_v<ToNativeType, Int128>)
{
static constexpr __int128 min_int128 = __int128(0x8000000000000000ll) << 64;

View File

@ -18,7 +18,6 @@
#include <Common/Exception.h>
#include <Common/StringUtils/StringUtils.h>
#include <Common/UInt128.h>
#include <Common/intExp.h>
#include <IO/CompressionMethod.h>
#include <IO/WriteBuffer.h>
@ -764,12 +763,6 @@ inline void writeText(const LocalDateTime & x, WriteBuffer & buf) { writeDateTim
inline void writeText(const UUID & x, WriteBuffer & buf) { writeUUIDText(x, buf); }
inline void writeText(const UInt128 & x, WriteBuffer & buf) { writeText(UUID(x), buf); }
template <typename T> inline T decimalScaleMultiplier(UInt32 scale);
template <> inline Int32 decimalScaleMultiplier<Int32>(UInt32 scale) { return common::exp10_i32(scale); }
template <> inline Int64 decimalScaleMultiplier<Int64>(UInt32 scale) { return common::exp10_i64(scale); }
template <> inline Int128 decimalScaleMultiplier<Int128>(UInt32 scale) { return common::exp10_i128(scale); }
template <typename T>
void writeText(Decimal<T> value, UInt32 scale, WriteBuffer & ostr)
{
@ -781,7 +774,7 @@ void writeText(Decimal<T> value, UInt32 scale, WriteBuffer & ostr)
T whole_part = value;
if (scale)
whole_part = value / decimalScaleMultiplier<T>(scale);
whole_part = value / Decimal<T>::getScaleMultiplier(scale);
writeIntText(whole_part, ostr);
if (scale)