16 #ifndef IMPALA_RUNTIME_DECIMAL_VALUE_H
17 #define IMPALA_RUNTIME_DECIMAL_VALUE_H
54 T max_value = DecimalUtil::GetScaleMultiplier<T>(t.
precision - t.
scale);
55 if (
abs(d) >= max_value) {
61 d *= DecimalUtil::GetScaleMultiplier<double>(t.
scale);
69 T max_value = DecimalUtil::GetScaleMultiplier<T>(t.
precision - t.
scale);
70 if (
abs(d) >= max_value) {
74 return DecimalValue(DecimalUtil::MultiplyByScale<T>(d, t));
111 if (x == y)
return 0;
112 if (x < y)
return -1;
120 bool* overflow)
const {
121 int delta_scale = src_type.
scale - dst_type.
scale;
123 T max_value = DecimalUtil::GetScaleMultiplier<T>(dst_type.
precision);
124 if (delta_scale >= 0) {
125 if (delta_scale != 0) result /= DecimalUtil::GetScaleMultiplier<T>(delta_scale);
129 *overflow |=
abs(result) >= max_value;
130 }
else if (delta_scale < 0) {
131 T mult = DecimalUtil::GetScaleMultiplier<T>(-delta_scale);
132 *overflow |=
abs(result) >= max_value / mult;
146 template<
typename RESULT_T>
148 const ColumnType& other_type,
int result_scale,
bool* overflow)
const {
149 DCHECK_EQ(result_scale, std::max(this_type.
scale, other_type.
scale));
153 if (
sizeof(RESULT_T) == 16) {
162 DCHECK(!*overflow) <<
"Cannot overflow unless result is Decimal16Value";
167 template<
typename RESULT_T>
169 const ColumnType& other_type,
int result_scale,
bool* overflow)
const {
170 return Add<RESULT_T>(this_type, -other, other_type, result_scale, overflow);
173 template<
typename RESULT_T>
175 const ColumnType& other_type,
int result_scale,
bool* overflow)
const {
181 RESULT_T x =
value();
182 RESULT_T y = other.
value();
183 if (x == 0 || y == 0) {
187 if (
sizeof(RESULT_T) == 16) {
191 RESULT_T result = x * y;
192 int delta_scale = this_type.
scale + other_type.
scale - result_scale;
197 DCHECK_GT(delta_scale, 0);
198 result /= DecimalUtil::GetScaleMultiplier<T>(delta_scale);
204 template<
typename RESULT_T>
206 const ColumnType& other_type,
int result_scale,
bool* is_nan,
bool* overflow)
208 DCHECK_GE(result_scale, this_type.
scale);
209 if (other.
value() == 0) {
217 int scale_by = result_scale + other_type.
scale - this_type.
scale;
220 if (
sizeof(T) == 16) {
221 int256_t x = DecimalUtil::MultiplyByScale<int256_t>(
227 int128_t x = DecimalUtil::MultiplyByScale<RESULT_T>(
value(), scale_by);
235 template<
typename RESULT_T>
237 const ColumnType& other_type,
int result_scale,
bool* is_nan,
bool* overflow)
239 DCHECK_EQ(result_scale, std::max(this_type.
scale, other_type.
scale));
240 if (other.
value() == 0) {
260 return Compare(this_type, other, other_type) == 0;
264 return Compare(this_type, other, other_type) != 0;
268 return Compare(this_type, other, other_type) >= 0;
272 return Compare(this_type, other, other_type) > 0;
276 return Compare(this_type, other, other_type) <= 0;
280 return Compare(this_type, other, other_type) < 0;
290 return value() / DecimalUtil::GetScaleMultiplier<T>(t.
scale);
295 return abs(
value()) % DecimalUtil::GetScaleMultiplier<T>(t.
scale);
300 return static_cast<double>(
value_) / powf(10.0, type.
scale);
303 inline uint32_t
Hash(
int seed = 0)
const {
318 template <
typename RESULT_T>
321 RESULT_T* x_scaled, RESULT_T* y_scaled) {
322 int delta_scale = x_type.
scale - y_type.
scale;
323 RESULT_T scale_factor = DecimalUtil::GetScaleMultiplier<RESULT_T>(
abs(delta_scale));
324 if (delta_scale == 0) {
325 *x_scaled = x.
value();
326 *y_scaled = y.
value();
327 }
else if (delta_scale > 0) {
328 if (
sizeof(RESULT_T) == 16 &&
332 *x_scaled = x.
value();
333 *y_scaled = y.
value() * scale_factor;
335 if (
sizeof(RESULT_T) == 16 &&
339 *x_scaled = x.
value() * scale_factor;
340 *y_scaled = y.
value();
365 *overflow |=
abs(v.
value()) > std::numeric_limits<int32_t>::max();
375 *overflow |=
abs(v.
value()) > std::numeric_limits<int32_t>::max();
379 *overflow |=
abs(v.
value()) > std::numeric_limits<int64_t>::max();
387 return os << d.
value();
390 return os << d.
value();
393 return os << d.
value();
412 const Decimal4Value& other,
const ColumnType& other_type)
const {
414 bool overflow = AdjustToSameScale(*
this, this_type, other, other_type, &x, &y);
415 DCHECK(!overflow) <<
"Overflow cannot happen with Decimal4Value";
416 if (x == y)
return 0;
417 if (x < y)
return -1;
421 inline int Decimal8Value::Compare(
const ColumnType& this_type,
422 const Decimal8Value& other,
const ColumnType& other_type)
const {
424 bool overflow = AdjustToSameScale(*
this, this_type, other, other_type, &x, &y);
425 DCHECK(!overflow) <<
"Overflow cannot happen with Decimal8Value";
426 if (x == y)
return 0;
427 if (x < y)
return -1;
431 inline int Decimal16Value::Compare(
const ColumnType& this_type,
432 const Decimal16Value& other,
const ColumnType& other_type)
const {
435 int delta_scale = this_type.scale - other_type.scale;
436 if (delta_scale > 0) {
437 y = DecimalUtil::MultiplyByScale<int256_t>(y, delta_scale);
438 }
else if (delta_scale < 0) {
439 x = DecimalUtil::MultiplyByScale<int256_t>(x, -delta_scale);
441 if (x == y)
return 0;
442 if (x < y)
return -1;
458 std::string str = std::string(last_char_idx,
'0');
462 T remaining_value = value_;
463 int first_digit_idx = 0;
465 remaining_value = -value_;
468 if (type.
scale > 0) {
469 int remaining_scale = type.
scale;
471 str[--last_char_idx] = (remaining_value % 10) +
'0';
472 remaining_value /= 10;
473 }
while (--remaining_scale > 0);
474 str[--last_char_idx] =
'.';
475 DCHECK_GT(last_char_idx, first_digit_idx) <<
"Not enough space remaining";
478 str[--last_char_idx] = (remaining_value % 10) +
'0';
479 remaining_value /= 10;
480 if (remaining_value == 0) {
482 if (last_char_idx > first_digit_idx) str.erase(0, last_char_idx - first_digit_idx);
486 }
while (last_char_idx > first_digit_idx);
487 if (value_ < 0) str[0] =
'-';
static DecimalValue FromDouble(const ColumnType &t, double d, bool *overflow)
bool Ge(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type) const
bool operator<(const DecimalValue &other) const
bool operator<=(const DecimalValue &other) const
bool operator==(const DecimalValue &other) const
bool Eq(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type) const
Comparison utilities.
DecimalValue ScaleTo(const ColumnType &src_type, const ColumnType &dst_type, bool *overflow) const
int128_t abs(const int128_t &x)
int128_t ConvertToInt128(int256_t x, int128_t max_value, bool *overflow)
int precision
Only set if type == TYPE_DECIMAL.
DecimalValue< int128_t > Decimal16Value
Decimal8Value ToDecimal8(const Decimal4Value &v, bool *overflow)
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void > > int256_t
Define 256 bit int type.
bool Le(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type) const
int256_t ConvertToInt256(const int128_t &x)
DecimalValue< RESULT_T > Subtract(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type, int result_scale, bool *overflow) const
Decimal16Value ToDecimal16(const Decimal4Value &v, bool *overflow)
std::size_t hash_value(const Decimal4Value &v)
This function must be called 'hash_value' to be picked up by boost.
DecimalValue operator-() const
static int128_t MAX_UNSCALED_DECIMAL
Maximum absolute value of int128_t that we use. This is 38 digits of 9's.
bool Lt(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type) const
DecimalValue< int64_t > Decimal8Value
DecimalValue< T > Abs() const
const T fractional_part(const ColumnType &t) const
Returns the value of the decimal after the decimal point.
bool operator>(const DecimalValue &other) const
static uint32_t Hash(const void *data, int32_t bytes, uint32_t seed)
bool Ne(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type) const
DecimalValue< int32_t > Decimal4Value
static bool AdjustToSameScale(const DecimalValue &x, const ColumnType &x_type, const DecimalValue &y, const ColumnType &y_type, RESULT_T *x_scaled, RESULT_T *y_scaled)
DecimalValue< RESULT_T > Divide(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type, int result_scale, bool *is_nan, bool *overflow) const
is_nan is set to true if 'other' is 0. The value returned is undefined.
bool operator>=(const DecimalValue &other) const
static DecimalValue FromInt(const ColumnType &t, int64_t d, bool *overflow)
Assigns *result as a decimal.
std::string ToString(const ColumnType &type) const
bool operator!=(const DecimalValue &other) const
bool Gt(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type) const
Decimal4Value ToDecimal4(const Decimal4Value &v, bool *overflow)
DecimalValue< RESULT_T > Multiply(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type, int result_scale, bool *overflow) const
DecimalValue< RESULT_T > Mod(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type, int result_scale, bool *is_nan, bool *overflow) const
is_nan is set to true if 'other' is 0. The value returned is undefined.
int Compare(const DecimalValue &other) const
ostream & operator<<(ostream &os, const map< TNetworkAddress, llama::TAllocatedResource > &resources)
DecimalValue< RESULT_T > Add(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type, int result_scale, bool *overflow) const
double ToDouble(const ColumnType &type) const
Returns an approximate double for this decimal.
const T whole_part(const ColumnType &t) const
Returns the value of the decimal before the decimal point.
uint32_t Hash(int seed=0) const
DecimalValue & operator=(const T &s)
__int128_t int128_t
We use the c++ int128_t type. This is stored using 16 bytes and very performant.