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.