2019-09-26 15:12:40 +00:00
|
|
|
#pragma once
|
|
|
|
// Moved Decimal-related functions out from Core/Types.h to reduce compilation time.
|
|
|
|
|
|
|
|
#include <Core/Types.h>
|
|
|
|
#include <Common/intExp.h>
|
|
|
|
|
|
|
|
#include <limits>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
template <typename T> 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>
|
|
|
|
struct DecimalComponents
|
|
|
|
{
|
|
|
|
T whole;
|
|
|
|
T fractional;
|
|
|
|
};
|
|
|
|
|
2019-10-03 07:27:28 +00:00
|
|
|
template <typename DecimalType>
|
|
|
|
DecimalType decimalFromComponents(const typename DecimalType::NativeType & whole, const typename DecimalType::NativeType & fractional, UInt32 scale)
|
2019-09-26 15:12:40 +00:00
|
|
|
{
|
2019-10-03 07:27:28 +00:00
|
|
|
using T = typename DecimalType::NativeType;
|
|
|
|
|
2019-09-26 15:12:40 +00:00
|
|
|
const auto mul = decimalScaleMultiplier<T>(scale);
|
|
|
|
const T value = whole * mul + fractional / decimalScaleMultiplier<T>(std::numeric_limits<T>::digits10 - scale);
|
2019-10-03 07:27:28 +00:00
|
|
|
return DecimalType(value);
|
2019-09-26 15:12:40 +00:00
|
|
|
}
|
|
|
|
|
2019-10-03 07:27:28 +00:00
|
|
|
template <typename DecimalType>
|
|
|
|
DecimalType decimalFromComponents(const DecimalComponents<typename DecimalType::NativeType> & components, UInt32 scale)
|
2019-09-26 15:12:40 +00:00
|
|
|
{
|
2019-10-03 07:27:28 +00:00
|
|
|
return decimalFromComponents<DecimalType>(components.whole, components.fractional, scale);
|
2019-09-26 15:12:40 +00:00
|
|
|
}
|
|
|
|
|
2019-10-03 07:27:28 +00:00
|
|
|
template <typename DecimalType>
|
|
|
|
DecimalComponents<typename DecimalType::NativeType> decimalSplit(const DecimalType & decimal, UInt32 scale)
|
2019-09-26 15:12:40 +00:00
|
|
|
{
|
|
|
|
if (scale == 0)
|
|
|
|
{
|
|
|
|
return {decimal.value, 0};
|
|
|
|
}
|
2019-10-03 07:27:28 +00:00
|
|
|
const auto scaleMultiplier = decimalScaleMultiplier<typename DecimalType::NativeType>(scale);
|
2019-09-26 15:12:40 +00:00
|
|
|
return {decimal.value / scaleMultiplier, decimal.value % scaleMultiplier};
|
|
|
|
}
|
|
|
|
|
2019-10-03 07:27:28 +00:00
|
|
|
template <typename DecimalType>
|
|
|
|
typename DecimalType::NativeType decimalWholePart(const DecimalType & decimal, size_t scale)
|
2019-09-26 15:12:40 +00:00
|
|
|
{
|
|
|
|
if (scale == 0)
|
|
|
|
return decimal.value;
|
|
|
|
|
2019-10-03 07:27:28 +00:00
|
|
|
return decimal.value / decimalScaleMultiplier<typename DecimalType::NativeType>(scale);
|
2019-09-26 15:12:40 +00:00
|
|
|
}
|
|
|
|
|
2019-10-03 07:27:28 +00:00
|
|
|
template <typename DecimalType>
|
|
|
|
typename DecimalType::NativeType decimalFractionalPart(const DecimalType & decimal, size_t scale)
|
2019-09-26 15:12:40 +00:00
|
|
|
{
|
2019-10-03 07:27:28 +00:00
|
|
|
using T = typename DecimalType::NativeType;
|
|
|
|
|
2019-09-26 15:12:40 +00:00
|
|
|
if (scale == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
T result = decimal.value;
|
|
|
|
if (result < T(0))
|
|
|
|
result *= T(-1);
|
|
|
|
|
|
|
|
return result % decimalScaleMultiplier<T>(scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|