You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-30 19:23:07 +03:00
MCOL-4409 Moved static Decimal conversion methods into VDecimal class
MCOL-4409 This patch combines VDecimal and Decimal and makes IDB_Decimal an alias for the result class MCOL-4409 More boilerplate reduction in Func_mod Removed couple TSInt128::toType() methods
This commit is contained in:
@ -630,7 +630,7 @@ int TypeHandlerSLongDouble::storeValueToField(rowgroup::Row &row, int pos,
|
||||
int TypeHandlerXDecimal::storeValueToField64(rowgroup::Row &row, int pos,
|
||||
StoreField *f) const
|
||||
{
|
||||
return f->store_decimal64(datatypes::VDecimal(row.getIntField(pos),
|
||||
return f->store_decimal64(datatypes::Decimal(row.getIntField(pos),
|
||||
f->scale(),
|
||||
f->precision()));
|
||||
}
|
||||
@ -640,7 +640,7 @@ int TypeHandlerXDecimal::storeValueToField128(rowgroup::Row &row, int pos,
|
||||
StoreField *f) const
|
||||
{
|
||||
int128_t* decPtr = row.getBinaryField<int128_t>(pos);
|
||||
return f->store_decimal128(datatypes::VDecimal(0,
|
||||
return f->store_decimal128(datatypes::Decimal(0,
|
||||
f->scale(),
|
||||
f->precision(),
|
||||
decPtr));
|
||||
@ -782,7 +782,7 @@ TypeHandlerXDecimal::format128(const SimpleValue &v,
|
||||
const
|
||||
{
|
||||
idbassert(isValidXDecimal128(attr));
|
||||
datatypes::VDecimal dec(0, attr.scale, attr.precision, v.toSInt128());
|
||||
datatypes::Decimal dec(0, attr.scale, attr.precision, v.toSInt128());
|
||||
return dec.toString(true);
|
||||
}
|
||||
|
||||
|
@ -727,8 +727,8 @@ public:
|
||||
virtual int store_float(float val) = 0;
|
||||
virtual int store_double(double val) = 0;
|
||||
virtual int store_long_double(long double val) = 0;
|
||||
virtual int store_decimal64(const datatypes::VDecimal& dec) = 0;
|
||||
virtual int store_decimal128(const datatypes::VDecimal& dec) = 0;
|
||||
virtual int store_decimal64(const datatypes::Decimal& dec) = 0;
|
||||
virtual int store_decimal128(const datatypes::Decimal& dec) = 0;
|
||||
virtual int store_lob(const char *str, size_t length) = 0;
|
||||
};
|
||||
|
||||
|
@ -49,9 +49,9 @@ namespace datatypes
|
||||
template<typename BinaryOperation,
|
||||
typename OpOverflowCheck,
|
||||
typename MultiplicationOverflowCheck>
|
||||
void addSubtractExecute(const VDecimal& l,
|
||||
const VDecimal& r,
|
||||
VDecimal& result,
|
||||
void addSubtractExecute(const Decimal& l,
|
||||
const Decimal& r,
|
||||
Decimal& result,
|
||||
BinaryOperation op,
|
||||
OpOverflowCheck opOverflowCheck,
|
||||
MultiplicationOverflowCheck mulOverflowCheck)
|
||||
@ -109,9 +109,9 @@ namespace datatypes
|
||||
|
||||
template<typename OpOverflowCheck,
|
||||
typename MultiplicationOverflowCheck>
|
||||
void divisionExecute(const VDecimal& l,
|
||||
const VDecimal& r,
|
||||
VDecimal& result,
|
||||
void divisionExecute(const Decimal& l,
|
||||
const Decimal& r,
|
||||
Decimal& result,
|
||||
OpOverflowCheck opOverflowCheck,
|
||||
MultiplicationOverflowCheck mulOverflowCheck)
|
||||
{
|
||||
@ -148,9 +148,9 @@ namespace datatypes
|
||||
|
||||
template<typename OpOverflowCheck,
|
||||
typename MultiplicationOverflowCheck>
|
||||
void multiplicationExecute(const VDecimal& l,
|
||||
const VDecimal& r,
|
||||
VDecimal& result,
|
||||
void multiplicationExecute(const Decimal& l,
|
||||
const Decimal& r,
|
||||
Decimal& result,
|
||||
OpOverflowCheck opOverflowCheck,
|
||||
MultiplicationOverflowCheck mulOverflowCheck)
|
||||
{
|
||||
@ -195,7 +195,7 @@ namespace datatypes
|
||||
}
|
||||
}
|
||||
|
||||
int Decimal::compare(const VDecimal& l, const VDecimal& r)
|
||||
int Decimal::compare(const Decimal& l, const Decimal& r)
|
||||
{
|
||||
int128_t divisorL, divisorR;
|
||||
getScaleDivisor(divisorL, l.scale);
|
||||
@ -242,8 +242,8 @@ namespace datatypes
|
||||
|
||||
// no overflow check
|
||||
template<>
|
||||
void Decimal::addition<int128_t, false>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::addition<int128_t, false>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
std::plus<int128_t> add;
|
||||
NoOverflowCheck noOverflowCheck;
|
||||
@ -252,8 +252,8 @@ namespace datatypes
|
||||
|
||||
// with overflow check
|
||||
template<>
|
||||
void Decimal::addition<int128_t, true>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::addition<int128_t, true>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
std::plus<int128_t> add;
|
||||
AdditionOverflowCheck overflowCheck;
|
||||
@ -263,8 +263,8 @@ namespace datatypes
|
||||
|
||||
// no overflow check
|
||||
template<>
|
||||
void Decimal::addition<int64_t, false>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::addition<int64_t, false>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
if (result.scale == l.scale && result.scale == r.scale)
|
||||
{
|
||||
@ -293,8 +293,8 @@ namespace datatypes
|
||||
|
||||
// with overflow check
|
||||
template<>
|
||||
void Decimal::addition<int64_t, true>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::addition<int64_t, true>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
AdditionOverflowCheck additionOverflowCheck;
|
||||
MultiplicationOverflowCheck mulOverflowCheck;
|
||||
@ -328,8 +328,8 @@ namespace datatypes
|
||||
|
||||
// no overflow check
|
||||
template<>
|
||||
void Decimal::subtraction<int128_t, false>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::subtraction<int128_t, false>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
std::minus<int128_t> subtract;
|
||||
NoOverflowCheck noOverflowCheck;
|
||||
@ -338,8 +338,8 @@ namespace datatypes
|
||||
|
||||
// with overflow check
|
||||
template<>
|
||||
void Decimal::subtraction<int128_t, true>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::subtraction<int128_t, true>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
std::minus<int128_t> subtract;
|
||||
SubtractionOverflowCheck overflowCheck;
|
||||
@ -349,8 +349,8 @@ namespace datatypes
|
||||
|
||||
// no overflow check
|
||||
template<>
|
||||
void Decimal::subtraction<int64_t, false>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::subtraction<int64_t, false>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
if (result.scale == l.scale && result.scale == r.scale)
|
||||
{
|
||||
@ -379,8 +379,8 @@ namespace datatypes
|
||||
|
||||
// with overflow check
|
||||
template<>
|
||||
void Decimal::subtraction<int64_t, true>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::subtraction<int64_t, true>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
SubtractionOverflowCheck subtractionOverflowCheck;
|
||||
MultiplicationOverflowCheck mulOverflowCheck;
|
||||
@ -414,8 +414,8 @@ namespace datatypes
|
||||
|
||||
// no overflow check
|
||||
template<>
|
||||
void Decimal::division<int128_t, false>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::division<int128_t, false>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
NoOverflowCheck noOverflowCheck;
|
||||
divisionExecute(l, r, result, noOverflowCheck, noOverflowCheck);
|
||||
@ -423,8 +423,8 @@ namespace datatypes
|
||||
|
||||
// With overflow check
|
||||
template<>
|
||||
void Decimal::division<int128_t, true>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::division<int128_t, true>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
DivisionOverflowCheck overflowCheck;
|
||||
MultiplicationOverflowCheck mulOverflowCheck;
|
||||
@ -434,8 +434,8 @@ namespace datatypes
|
||||
// no overflow check
|
||||
// We rely on the zero check from ArithmeticOperator::execute
|
||||
template<>
|
||||
void Decimal::division<int64_t, false>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::division<int64_t, false>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
if (result.scale >= l.scale - r.scale)
|
||||
result.value = (int64_t)(( (l.value > 0 && r.value > 0) || (l.value < 0 && r.value < 0) ?
|
||||
@ -449,8 +449,8 @@ namespace datatypes
|
||||
|
||||
// With overflow check
|
||||
template<>
|
||||
void Decimal::division<int64_t, true>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::division<int64_t, true>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
DivisionOverflowCheck divisionOverflowCheck;
|
||||
|
||||
@ -469,8 +469,8 @@ namespace datatypes
|
||||
|
||||
// no overflow check
|
||||
template<>
|
||||
void Decimal::multiplication<int128_t, false>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::multiplication<int128_t, false>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
MultiplicationNoOverflowCheck noOverflowCheck;
|
||||
multiplicationExecute(l, r, result, noOverflowCheck, noOverflowCheck);
|
||||
@ -478,8 +478,8 @@ namespace datatypes
|
||||
|
||||
// With overflow check
|
||||
template<>
|
||||
void Decimal::multiplication<int128_t, true>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::multiplication<int128_t, true>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
MultiplicationOverflowCheck mulOverflowCheck;
|
||||
multiplicationExecute(l, r, result, mulOverflowCheck, mulOverflowCheck);
|
||||
@ -487,8 +487,8 @@ namespace datatypes
|
||||
|
||||
// no overflow check
|
||||
template<>
|
||||
void Decimal::multiplication<int64_t, false>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::multiplication<int64_t, false>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
if (result.scale >= l.scale + r.scale)
|
||||
result.value = l.value * r.value * mcs_pow_10[result.scale - (l.scale + r.scale)];
|
||||
@ -500,8 +500,8 @@ namespace datatypes
|
||||
|
||||
// With overflow check
|
||||
template<>
|
||||
void Decimal::multiplication<int64_t, true>(const VDecimal& l,
|
||||
const VDecimal& r, VDecimal& result)
|
||||
void Decimal::multiplication<int64_t, true>(const Decimal& l,
|
||||
const Decimal& r, Decimal& result)
|
||||
{
|
||||
MultiplicationOverflowCheck mulOverflowCheck;
|
||||
|
||||
@ -521,7 +521,7 @@ namespace datatypes
|
||||
}
|
||||
|
||||
// Writes integer part of a Decimal using int128 argument provided
|
||||
uint8_t VDecimal::writeIntPart(const int128_t& x,
|
||||
uint8_t Decimal::writeIntPart(const int128_t& x,
|
||||
char* buf,
|
||||
const uint8_t buflen) const
|
||||
{
|
||||
@ -552,7 +552,7 @@ namespace datatypes
|
||||
high = intPart / maxUint64divisor;
|
||||
break;
|
||||
default:
|
||||
throw logging::QueryDataExcept("VDecimal::writeIntPart() bad scale",
|
||||
throw logging::QueryDataExcept("Decimal::writeIntPart() bad scale",
|
||||
logging::formatErr);
|
||||
}
|
||||
|
||||
@ -560,14 +560,14 @@ namespace datatypes
|
||||
uint8_t written = p - buf;
|
||||
if (buflen <= written)
|
||||
{
|
||||
throw logging::QueryDataExcept("VDecimal::writeIntPart() char buffer overflow.",
|
||||
throw logging::QueryDataExcept("Decimal::writeIntPart() char buffer overflow.",
|
||||
logging::formatErr);
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
uint8_t VDecimal::writeFractionalPart(const int128_t& x,
|
||||
uint8_t Decimal::writeFractionalPart(const int128_t& x,
|
||||
char* buf,
|
||||
const uint8_t buflen) const
|
||||
{
|
||||
@ -605,7 +605,7 @@ namespace datatypes
|
||||
// The method writes Decimal based on TSInt128 with scale provided.
|
||||
// It first writes sign, then extracts integer part
|
||||
// prints delimiter and then decimal part.
|
||||
std::string VDecimal::toStringTSInt128WithScale() const
|
||||
std::string Decimal::toStringTSInt128WithScale() const
|
||||
{
|
||||
char buf[Decimal::MAXLENGTH16BYTES];
|
||||
uint8_t left = sizeof(buf);
|
||||
@ -633,13 +633,13 @@ namespace datatypes
|
||||
uint8_t written = p - buf;
|
||||
if (sizeof(buf) <= written)
|
||||
{
|
||||
throw logging::QueryDataExcept("VDecimal::toString() char buffer overflow.",
|
||||
throw logging::QueryDataExcept("Decimal::toString() char buffer overflow.",
|
||||
logging::formatErr);
|
||||
}
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
std::string VDecimal::toStringTSInt64() const
|
||||
std::string Decimal::toStringTSInt64() const
|
||||
{
|
||||
char buf[Decimal::MAXLENGTH8BYTES];
|
||||
// Need 19 digits maxium to hold a sum result of 18 digits decimal column.
|
||||
@ -706,7 +706,7 @@ namespace datatypes
|
||||
}
|
||||
|
||||
// Dispatcher method for toString() implementations
|
||||
std::string VDecimal::toString(bool hasTSInt128) const
|
||||
std::string Decimal::toString(bool hasTSInt128) const
|
||||
{
|
||||
// There must be no empty at this point though
|
||||
if (isNull())
|
||||
@ -730,7 +730,7 @@ namespace datatypes
|
||||
return std::to_string(value);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const VDecimal& dec)
|
||||
std::ostream& operator<<(std::ostream& os, const Decimal& dec)
|
||||
{
|
||||
os << dec.toString();
|
||||
return os;
|
||||
|
@ -26,11 +26,13 @@
|
||||
#include "widedecimalutils.h"
|
||||
#include "mcs_int128.h"
|
||||
#include "mcs_float128.h"
|
||||
#include "checks.h"
|
||||
#include "branchpred.h"
|
||||
|
||||
|
||||
namespace datatypes
|
||||
{
|
||||
class VDecimal;
|
||||
class Decimal;
|
||||
}
|
||||
|
||||
// A class by Fabio Fernandes pulled off of stackoverflow
|
||||
@ -158,21 +160,16 @@ inline void getScaleDivisor(T& divisor, const int8_t scale)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief Contains subset of decimal related operations.
|
||||
|
||||
Most of the methods are static to allow to call them from
|
||||
the existing code.
|
||||
The main purpose of the class is to collect methods for a
|
||||
base Datatype class.
|
||||
*/
|
||||
class Decimal
|
||||
// @brief The class for Decimal related operations
|
||||
// The class contains Decimal related operations are scale and
|
||||
// precision aware.
|
||||
// This class will inherit from:
|
||||
// DecimalMeta class that stores scale and precision
|
||||
// Storage classes TSInt128 and int64
|
||||
// !!! There are some static classes that will exists during transition period.
|
||||
class Decimal: public TSInt128
|
||||
{
|
||||
public:
|
||||
Decimal() { };
|
||||
~Decimal() { };
|
||||
|
||||
static constexpr uint8_t MAXLENGTH16BYTES = TSInt128::maxLength();
|
||||
static constexpr uint8_t MAXLENGTH8BYTES = 23;
|
||||
|
||||
@ -200,44 +197,44 @@ class Decimal
|
||||
static constexpr int128_t maxInt128 = (int128_t(0x7FFFFFFFFFFFFFFFLL) << 64) + 0xFFFFFFFFFFFFFFFFLL;
|
||||
|
||||
/**
|
||||
@brief Compares two VDecimal taking scale into account.
|
||||
@brief Compares two Decimal taking scale into account.
|
||||
*/
|
||||
static int compare(const VDecimal& l, const VDecimal& r);
|
||||
static int compare(const Decimal& l, const Decimal& r);
|
||||
/**
|
||||
@brief Addition template that supports overflow check and
|
||||
two internal representations of decimal.
|
||||
*/
|
||||
template<typename T, bool overflow>
|
||||
static void addition(const VDecimal& l,
|
||||
const VDecimal& r,
|
||||
VDecimal& result);
|
||||
static void addition(const Decimal& l,
|
||||
const Decimal& r,
|
||||
Decimal& result);
|
||||
|
||||
/**
|
||||
@brief Subtraction template that supports overflow check and
|
||||
two internal representations of decimal.
|
||||
*/
|
||||
template<typename T, bool overflow>
|
||||
static void subtraction(const VDecimal& l,
|
||||
const VDecimal& r,
|
||||
VDecimal& result);
|
||||
static void subtraction(const Decimal& l,
|
||||
const Decimal& r,
|
||||
Decimal& result);
|
||||
|
||||
/**
|
||||
@brief Division template that supports overflow check and
|
||||
two internal representations of decimal.
|
||||
*/
|
||||
template<typename T, bool overflow>
|
||||
static void division(const VDecimal& l,
|
||||
const VDecimal& r,
|
||||
VDecimal& result);
|
||||
static void division(const Decimal& l,
|
||||
const Decimal& r,
|
||||
Decimal& result);
|
||||
|
||||
/**
|
||||
@brief Multiplication template that supports overflow check and
|
||||
two internal representations of decimal.
|
||||
*/
|
||||
template<typename T, bool overflow>
|
||||
static void multiplication(const VDecimal& l,
|
||||
const VDecimal& r,
|
||||
VDecimal& result);
|
||||
static void multiplication(const Decimal& l,
|
||||
const Decimal& r,
|
||||
Decimal& result);
|
||||
|
||||
/**
|
||||
@brief The method detects whether decimal type is wide
|
||||
@ -249,85 +246,6 @@ class Decimal
|
||||
&& precision <= INT128MAXPRECISION;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief The method converts a __float128 value to an int64_t.
|
||||
*/
|
||||
static inline int64_t getInt64FromFloat128(const __float128& value)
|
||||
{
|
||||
if (value > static_cast<__float128>(INT64_MAX))
|
||||
return INT64_MAX;
|
||||
else if (value < static_cast<__float128>(INT64_MIN))
|
||||
return INT64_MIN;
|
||||
|
||||
return static_cast<int64_t>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief The method converts a __float128 value to an uint64_t.
|
||||
*/
|
||||
static inline uint64_t getUInt64FromFloat128(const __float128& value)
|
||||
{
|
||||
if (value > static_cast<__float128>(UINT64_MAX))
|
||||
return UINT64_MAX;
|
||||
else if (value < 0)
|
||||
return 0;
|
||||
|
||||
return static_cast<uint64_t>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief The method converts a wide decimal value to an uint32_t.
|
||||
*/
|
||||
static inline uint32_t getUInt32FromWideDecimal(const int128_t& value)
|
||||
{
|
||||
if (value > static_cast<int128_t>(UINT32_MAX))
|
||||
return UINT32_MAX;
|
||||
else if (value < 0)
|
||||
return 0;
|
||||
|
||||
return static_cast<uint32_t>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief The method converts a wide decimal value to an int32_t.
|
||||
*/
|
||||
static inline int32_t getInt32FromWideDecimal(const int128_t& value)
|
||||
{
|
||||
if (value > static_cast<int128_t>(INT32_MAX))
|
||||
return INT32_MAX;
|
||||
else if (value < static_cast<int128_t>(INT32_MIN))
|
||||
return INT32_MIN;
|
||||
|
||||
return static_cast<int32_t>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief The method converts a wide decimal value to an uint64_t.
|
||||
*/
|
||||
static inline uint64_t getUInt64FromWideDecimal(const int128_t& value)
|
||||
{
|
||||
if (value > static_cast<int128_t>(UINT64_MAX))
|
||||
return UINT64_MAX;
|
||||
else if (value < 0)
|
||||
return 0;
|
||||
|
||||
return static_cast<uint64_t>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief The method converts a wide decimal value to an int64_t,
|
||||
saturating the value if necessary.
|
||||
*/
|
||||
static inline int64_t getInt64FromWideDecimal(const int128_t& value)
|
||||
{
|
||||
if (value > static_cast<int128_t>(INT64_MAX))
|
||||
return INT64_MAX;
|
||||
else if (value < static_cast<int128_t>(INT64_MIN))
|
||||
return INT64_MIN;
|
||||
|
||||
return static_cast<int64_t>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief MDB increases scale by up to 4 digits calculating avg()
|
||||
*/
|
||||
@ -340,7 +258,461 @@ class Decimal
|
||||
scale += (scaleAvailable >= MAXSCALEINC4AVG) ? MAXSCALEINC4AVG : scaleAvailable;
|
||||
precision += (precisionAvailable >= MAXSCALEINC4AVG) ? MAXSCALEINC4AVG : precisionAvailable;
|
||||
}
|
||||
};
|
||||
|
||||
Decimal(): value(0), scale(0), precision(0)
|
||||
{
|
||||
}
|
||||
|
||||
Decimal(int64_t val, int8_t s, uint8_t p, const int128_t &val128 = 0) :
|
||||
TSInt128(val128),
|
||||
value(val),
|
||||
scale(s),
|
||||
precision(p)
|
||||
{ }
|
||||
|
||||
Decimal(int64_t unused, int8_t s, uint8_t p, const int128_t* val128Ptr) :
|
||||
TSInt128(val128Ptr),
|
||||
value(unused),
|
||||
scale(s),
|
||||
precision(p)
|
||||
{ }
|
||||
|
||||
Decimal(const TSInt128& val128, int8_t s, uint8_t p) :
|
||||
TSInt128(val128),
|
||||
value(0),
|
||||
scale(s),
|
||||
precision(p)
|
||||
{ }
|
||||
|
||||
|
||||
int decimalComp(const Decimal& d) const
|
||||
{
|
||||
lldiv_t d1 = lldiv(value, static_cast<int64_t>(mcs_pow_10[scale]));
|
||||
lldiv_t d2 = lldiv(d.value, static_cast<int64_t>(mcs_pow_10[d.scale]));
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if (d1.quot > d2.quot)
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
else if (d1.quot < d2.quot)
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// rem carries the value's sign, but needs to be normalized.
|
||||
int64_t s = scale - d.scale;
|
||||
|
||||
if (s < 0)
|
||||
{
|
||||
if ((d1.rem * static_cast<int64_t>(mcs_pow_10[-s])) > d2.rem)
|
||||
ret = 1;
|
||||
else if ((d1.rem * static_cast<int64_t>(mcs_pow_10[-s])) < d2.rem)
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d1.rem > (d2.rem * static_cast<int64_t>(mcs_pow_10[s])))
|
||||
ret = 1;
|
||||
else if (d1.rem < (d2.rem * static_cast<int64_t>(mcs_pow_10[s])))
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
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<double>(tmpval);
|
||||
}
|
||||
|
||||
inline operator double() const
|
||||
{
|
||||
return toDouble();
|
||||
}
|
||||
|
||||
inline long double toLongDouble() const
|
||||
{
|
||||
datatypes::TFloat128 y(s128Value);
|
||||
return static_cast<long double>(y);
|
||||
}
|
||||
|
||||
|
||||
// This method returns integral part as a TSInt128 and
|
||||
// fractional part as a TFloat128
|
||||
inline std::pair<TSInt128, TFloat128> getIntegralAndDividedFractional() const
|
||||
{
|
||||
int128_t scaleDivisor;
|
||||
getScaleDivisor(scaleDivisor, scale);
|
||||
return std::make_pair(TSInt128(s128Value / scaleDivisor),
|
||||
TFloat128((__float128)(s128Value % scaleDivisor) / scaleDivisor));
|
||||
}
|
||||
|
||||
// This method returns integral part as a TSInt128 and
|
||||
// fractional part as a TFloat128
|
||||
inline std::pair<TSInt128, TSInt128> getIntegralAndFractional() const
|
||||
{
|
||||
int128_t scaleDivisor;
|
||||
getScaleDivisor(scaleDivisor, scale);
|
||||
return std::make_pair(TSInt128(s128Value / scaleDivisor),
|
||||
TSInt128(s128Value % scaleDivisor));
|
||||
}
|
||||
|
||||
inline std::tuple<TSInt128, TSInt128, TSInt128> getIntegralFractionalAndDivisor() const
|
||||
{
|
||||
int128_t scaleDivisor;
|
||||
getScaleDivisor(scaleDivisor, scale);
|
||||
return std::make_tuple(TSInt128(s128Value / scaleDivisor),
|
||||
TSInt128(s128Value % scaleDivisor),
|
||||
TSInt128(scaleDivisor));
|
||||
}
|
||||
|
||||
inline TSInt128 getIntegralPart() const
|
||||
{
|
||||
int128_t scaleDivisor = 0;
|
||||
if(LIKELY(utils::is_nonnegative(scale)))
|
||||
{
|
||||
return TSInt128(getIntegralPartNonNegativeScale(scaleDivisor));
|
||||
}
|
||||
return TSInt128(getIntegralPartNegativeScale(scaleDivisor));
|
||||
}
|
||||
|
||||
// !!! This is a very hevyweight rouding style
|
||||
// Argument determines if it is a ceil
|
||||
// rounding or not. 0 - ceil rounding
|
||||
inline TSInt128 getRoundedIntegralPart(const uint8_t roundingFactor = 0) const
|
||||
{
|
||||
int128_t flooredScaleDivisor = 0;
|
||||
int128_t roundedValue = getIntegralPartNonNegativeScale(flooredScaleDivisor);
|
||||
int128_t ceiledScaleDivisor = (flooredScaleDivisor <= 10) ? 1 : (flooredScaleDivisor / 10);
|
||||
int128_t leftO = (s128Value - roundedValue * flooredScaleDivisor) / ceiledScaleDivisor;
|
||||
if (leftO > roundingFactor)
|
||||
{
|
||||
roundedValue++;
|
||||
}
|
||||
|
||||
return TSInt128(roundedValue);
|
||||
}
|
||||
|
||||
inline TSInt128 getPosNegRoundedIntegralPart(const uint8_t roundingFactor = 0) const
|
||||
{
|
||||
int128_t flooredScaleDivisor = 0;
|
||||
int128_t roundedValue = getIntegralPartNonNegativeScale(flooredScaleDivisor);
|
||||
int128_t ceiledScaleDivisor = (flooredScaleDivisor <= 10) ? 1 : (flooredScaleDivisor / 10);
|
||||
int128_t leftO = (s128Value - roundedValue * flooredScaleDivisor) / ceiledScaleDivisor;
|
||||
if (utils::is_nonnegative(roundedValue) && leftO > roundingFactor)
|
||||
{
|
||||
roundedValue++;
|
||||
}
|
||||
if (utils::is_negative(roundedValue) && leftO < -roundingFactor)
|
||||
{
|
||||
roundedValue--;
|
||||
}
|
||||
|
||||
return TSInt128(roundedValue);
|
||||
}
|
||||
|
||||
// MOD operator for an integer divisor to be used
|
||||
// for integer rhs
|
||||
inline TSInt128 operator%(const TSInt128& div) const
|
||||
{
|
||||
if (!isScaled())
|
||||
{
|
||||
return s128Value % div.getValue();
|
||||
}
|
||||
// Scale the value and calculate
|
||||
// (LHS.value % RHS.value) * LHS.scaleMultiplier + LHS.scale_div_remainder
|
||||
auto integralFractionalDivisor = getIntegralFractionalAndDivisor();
|
||||
return (std::get<0>(integralFractionalDivisor) % div.getValue()) * std::get<2>(integralFractionalDivisor) + std::get<1>(integralFractionalDivisor);
|
||||
}
|
||||
|
||||
bool operator==(const Decimal& rhs) const
|
||||
{
|
||||
if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value == rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) == 0);
|
||||
}
|
||||
else if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision <= datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
const_cast<Decimal&>(rhs).s128Value = rhs.value;
|
||||
|
||||
if (scale == rhs.scale)
|
||||
return s128Value == rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) == 0);
|
||||
}
|
||||
else if (precision <= datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value == rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value == rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator>(const Decimal& rhs) const
|
||||
{
|
||||
if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value > rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) > 0);
|
||||
}
|
||||
else if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision <= datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
|
||||
|
||||
if (scale == rhstmp.scale)
|
||||
return s128Value > rhstmp.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhstmp) > 0);
|
||||
}
|
||||
else if (precision <= datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value > rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value > rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) > 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(const Decimal& rhs) const
|
||||
{
|
||||
if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value < rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) < 0);
|
||||
}
|
||||
else if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision <= datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
|
||||
|
||||
if (scale == rhstmp.scale)
|
||||
return s128Value < rhstmp.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhstmp) < 0);
|
||||
}
|
||||
else if (precision <= datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value < rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) < 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value < rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) < 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator>=(const Decimal& rhs) const
|
||||
{
|
||||
if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value >= rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) >= 0);
|
||||
}
|
||||
else if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision <= datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
|
||||
|
||||
if (scale == rhstmp.scale)
|
||||
return s128Value >= rhstmp.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhstmp) >= 0);
|
||||
}
|
||||
else if (precision <= datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value >= rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) >= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value >= rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<=(const Decimal& rhs) const
|
||||
{
|
||||
if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value <= rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) <= 0);
|
||||
}
|
||||
else if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision <= datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
|
||||
|
||||
if (scale == rhstmp.scale)
|
||||
return s128Value <= rhstmp.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhstmp) <= 0);
|
||||
}
|
||||
else if (precision <= datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value <= rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) <= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value <= rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) <= 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator!=(const Decimal& rhs) const
|
||||
{
|
||||
if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value != rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) != 0);
|
||||
}
|
||||
else if (precision > datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision <= datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
|
||||
|
||||
if (scale == rhstmp.scale)
|
||||
return s128Value != rhstmp.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhstmp) != 0);
|
||||
}
|
||||
else if (precision <= datatypes::INT64MAXPRECISION &&
|
||||
rhs.precision > datatypes::INT64MAXPRECISION)
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value != rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value != rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool isTSInt128ByPrecision() const
|
||||
{
|
||||
return precision > INT64MAXPRECISION
|
||||
&& precision <= INT128MAXPRECISION;
|
||||
}
|
||||
|
||||
inline bool isScaled() const
|
||||
{
|
||||
return scale != 0;
|
||||
}
|
||||
|
||||
// hasTSInt128 explicitly tells to print int128 out in cases
|
||||
// where precision can't detect decimal type properly, e.g.
|
||||
// DECIMAL(10)/DECIMAL(38)
|
||||
std::string toString(bool hasTSInt128 = false) const;
|
||||
friend std::ostream& operator<<(std::ostream& os, const Decimal& dec);
|
||||
|
||||
int64_t value;
|
||||
int8_t scale; // 0~38
|
||||
uint8_t precision; // 1~38
|
||||
|
||||
// STRICTLY for unit tests!!!
|
||||
void setTSInt64Value(const int64_t x) { value = x; }
|
||||
void setTSInt128Value(const int128_t& x) { s128Value = x; }
|
||||
void setScale(const uint8_t x) { scale = x; }
|
||||
|
||||
private:
|
||||
uint8_t writeIntPart(const int128_t& x,
|
||||
char* buf,
|
||||
const uint8_t buflen) const;
|
||||
uint8_t writeFractionalPart(const int128_t& x,
|
||||
char* buf,
|
||||
const uint8_t buflen) const;
|
||||
std::string toStringTSInt128WithScale() const;
|
||||
std::string toStringTSInt64() const;
|
||||
|
||||
inline int128_t getIntegralPartNonNegativeScale(int128_t& scaleDivisor) const
|
||||
{
|
||||
getScaleDivisor(scaleDivisor, scale);
|
||||
return s128Value / scaleDivisor;
|
||||
}
|
||||
|
||||
inline int128_t getIntegralPartNegativeScale(int128_t& scaleDivisor) const
|
||||
{
|
||||
getScaleDivisor(scaleDivisor, -scale);
|
||||
// Calls for overflow check
|
||||
return s128Value * scaleDivisor;
|
||||
}
|
||||
}; //end of Decimal
|
||||
|
||||
/**
|
||||
@brief The structure contains an overflow check for int128
|
||||
@ -480,330 +852,5 @@ struct NoOverflowCheck {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief VDecimal type
|
||||
*
|
||||
*/
|
||||
class VDecimal: public TSInt128
|
||||
{
|
||||
public:
|
||||
VDecimal(): value(0), scale(0), precision(0)
|
||||
{
|
||||
}
|
||||
|
||||
VDecimal(int64_t val, int8_t s, uint8_t p, const int128_t &val128 = 0) :
|
||||
TSInt128(val128),
|
||||
value(val),
|
||||
scale(s),
|
||||
precision(p)
|
||||
{ }
|
||||
|
||||
VDecimal(int64_t unused, int8_t s, uint8_t p, const int128_t* val128Ptr) :
|
||||
TSInt128(val128Ptr),
|
||||
value(unused),
|
||||
scale(s),
|
||||
precision(p)
|
||||
{ }
|
||||
|
||||
|
||||
int decimalComp(const VDecimal& d) const
|
||||
{
|
||||
lldiv_t d1 = lldiv(value, static_cast<int64_t>(mcs_pow_10[scale]));
|
||||
lldiv_t d2 = lldiv(d.value, static_cast<int64_t>(mcs_pow_10[d.scale]));
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if (d1.quot > d2.quot)
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
else if (d1.quot < d2.quot)
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// rem carries the value's sign, but needs to be normalized.
|
||||
int64_t s = scale - d.scale;
|
||||
|
||||
if (s < 0)
|
||||
{
|
||||
if ((d1.rem * static_cast<int64_t>(mcs_pow_10[-s])) > d2.rem)
|
||||
ret = 1;
|
||||
else if ((d1.rem * static_cast<int64_t>(mcs_pow_10[-s])) < d2.rem)
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d1.rem > (d2.rem * static_cast<int64_t>(mcs_pow_10[s])))
|
||||
ret = 1;
|
||||
else if (d1.rem < (d2.rem * static_cast<int64_t>(mcs_pow_10[s])))
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
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<double>(tmpval);
|
||||
}
|
||||
|
||||
inline operator double() const
|
||||
{
|
||||
return toDouble();
|
||||
}
|
||||
|
||||
bool operator==(const VDecimal& rhs) const
|
||||
{
|
||||
if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value == rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) == 0);
|
||||
}
|
||||
else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
const_cast<VDecimal&>(rhs).s128Value = rhs.value;
|
||||
|
||||
if (scale == rhs.scale)
|
||||
return s128Value == rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) == 0);
|
||||
}
|
||||
else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value == rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value == rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator>(const VDecimal& rhs) const
|
||||
{
|
||||
if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value > rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) > 0);
|
||||
}
|
||||
else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
VDecimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
|
||||
|
||||
if (scale == rhstmp.scale)
|
||||
return s128Value > rhstmp.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhstmp) > 0);
|
||||
}
|
||||
else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value > rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value > rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) > 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(const VDecimal& rhs) const
|
||||
{
|
||||
if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value < rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) < 0);
|
||||
}
|
||||
else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
VDecimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
|
||||
|
||||
if (scale == rhstmp.scale)
|
||||
return s128Value < rhstmp.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhstmp) < 0);
|
||||
}
|
||||
else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value < rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) < 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value < rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) < 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator>=(const VDecimal& rhs) const
|
||||
{
|
||||
if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value >= rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) >= 0);
|
||||
}
|
||||
else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
VDecimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
|
||||
|
||||
if (scale == rhstmp.scale)
|
||||
return s128Value >= rhstmp.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhstmp) >= 0);
|
||||
}
|
||||
else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value >= rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) >= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value >= rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<=(const VDecimal& rhs) const
|
||||
{
|
||||
if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value <= rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) <= 0);
|
||||
}
|
||||
else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
VDecimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
|
||||
|
||||
if (scale == rhstmp.scale)
|
||||
return s128Value <= rhstmp.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhstmp) <= 0);
|
||||
}
|
||||
else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value <= rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) <= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value <= rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) <= 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator!=(const VDecimal& rhs) const
|
||||
{
|
||||
if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return s128Value != rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhs) != 0);
|
||||
}
|
||||
else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
VDecimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
|
||||
|
||||
if (scale == rhstmp.scale)
|
||||
return s128Value != rhstmp.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(*this, rhstmp) != 0);
|
||||
}
|
||||
else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision())
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return (int128_t) value != rhs.s128Value;
|
||||
else
|
||||
return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale == rhs.scale)
|
||||
return value != rhs.value;
|
||||
else
|
||||
return (decimalComp(rhs) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool isTSInt128ByPrecision() const
|
||||
{
|
||||
return precision > INT64MAXPRECISION
|
||||
&& precision <= INT128MAXPRECISION;
|
||||
}
|
||||
// hasTSInt128 explicitly tells to print int128 out in cases
|
||||
// where precision can't detect decimal type properly, e.g.
|
||||
// DECIMAL(10)/DECIMAL(38)
|
||||
std::string toString(bool hasTSInt128 = false) const;
|
||||
friend std::ostream& operator<<(std::ostream& os, const VDecimal& dec);
|
||||
|
||||
int64_t value;
|
||||
int8_t scale; // 0~38
|
||||
uint8_t precision; // 1~38
|
||||
|
||||
// STRICTLY for unit tests!!!
|
||||
void setTSInt64Value(const int64_t x) { value = x; }
|
||||
void setTSInt128Value(const int128_t& x) { s128Value = x; }
|
||||
void setScale(const uint8_t x) { scale = x; }
|
||||
|
||||
private:
|
||||
uint8_t writeIntPart(const int128_t& x,
|
||||
char* buf,
|
||||
const uint8_t buflen) const;
|
||||
uint8_t writeFractionalPart(const int128_t& x,
|
||||
char* buf,
|
||||
const uint8_t buflen) const;
|
||||
std::string toStringTSInt128WithScale() const;
|
||||
std::string toStringTSInt64() const;
|
||||
|
||||
};
|
||||
|
||||
} //end of namespace
|
||||
#endif
|
||||
|
@ -25,9 +25,28 @@
|
||||
namespace datatypes
|
||||
{
|
||||
|
||||
//class TSInt128;
|
||||
class TSInt128;
|
||||
class TFloat128;
|
||||
using int128_t = __int128;
|
||||
|
||||
// Type defined integral types
|
||||
// for templates
|
||||
template <typename T>
|
||||
struct get_integral_type {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct get_integral_type<TFloat128>{
|
||||
typedef __float128 type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct get_integral_type<TSInt128>{
|
||||
typedef int128_t type;
|
||||
};
|
||||
|
||||
|
||||
class TFloat128
|
||||
{
|
||||
public:
|
||||
@ -66,6 +85,40 @@ class TFloat128
|
||||
return toLongDouble();
|
||||
}
|
||||
|
||||
inline int64_t toTSInt64() const
|
||||
{
|
||||
if (value > static_cast<__float128>(INT64_MAX))
|
||||
return INT64_MAX;
|
||||
else if (value < static_cast<__float128>(INT64_MIN))
|
||||
return INT64_MIN;
|
||||
|
||||
return static_cast<int64_t>(value);
|
||||
}
|
||||
|
||||
inline operator int64_t() const
|
||||
{
|
||||
return toTSInt64();
|
||||
}
|
||||
|
||||
inline int64_t toTUInt64() const
|
||||
{
|
||||
if (value > static_cast<__float128>(UINT64_MAX))
|
||||
return UINT64_MAX;
|
||||
else if (value < 0)
|
||||
return 0;
|
||||
|
||||
return static_cast<uint64_t>(value);
|
||||
}
|
||||
|
||||
inline operator uint64_t() const
|
||||
{
|
||||
return toTUInt64();
|
||||
}
|
||||
|
||||
inline TFloat128 operator+(const TFloat128& rhs) const
|
||||
{
|
||||
return TFloat128(value + rhs.value);
|
||||
}
|
||||
|
||||
inline long double toLongDouble() const
|
||||
{
|
||||
|
@ -117,50 +117,5 @@ namespace datatypes
|
||||
return os;
|
||||
}
|
||||
|
||||
// The method converts a wide decimal s128Value to an int64_t,
|
||||
// saturating the s128Value if necessary.
|
||||
inline int64_t TSInt128::getInt64FromWideDecimal()
|
||||
{
|
||||
if (s128Value > static_cast<int128_t>(INT64_MAX))
|
||||
return INT64_MAX;
|
||||
else if (s128Value < static_cast<int128_t>(INT64_MIN))
|
||||
return INT64_MIN;
|
||||
|
||||
return static_cast<int64_t>(s128Value);
|
||||
}
|
||||
|
||||
// The method converts a wide decimal s128Value to an uint32_t.
|
||||
inline uint32_t TSInt128::getUInt32FromWideDecimal()
|
||||
{
|
||||
if (s128Value > static_cast<int128_t>(UINT32_MAX))
|
||||
return UINT32_MAX;
|
||||
else if (s128Value < 0)
|
||||
return 0;
|
||||
|
||||
return static_cast<uint32_t>(s128Value);
|
||||
}
|
||||
|
||||
// The method converts a wide decimal s128Value to an uint64_t.
|
||||
inline uint64_t TSInt128::getUInt64FromWideDecimal()
|
||||
{
|
||||
if (s128Value > static_cast<int128_t>(UINT64_MAX))
|
||||
return UINT64_MAX;
|
||||
else if (s128Value < 0)
|
||||
return 0;
|
||||
|
||||
return static_cast<uint64_t>(s128Value);
|
||||
}
|
||||
|
||||
// The method converts a wide decimal s128Value to an int32_t.
|
||||
inline int32_t TSInt128::getInt32FromWideDecimal()
|
||||
{
|
||||
if (s128Value > static_cast<int128_t>(INT32_MAX))
|
||||
return INT32_MAX;
|
||||
else if (s128Value < static_cast<int128_t>(INT32_MIN))
|
||||
return INT32_MIN;
|
||||
|
||||
return static_cast<int32_t>(s128Value);
|
||||
}
|
||||
|
||||
} // end of namespace datatypes
|
||||
// vim:ts=2 sw=2:
|
||||
|
@ -200,16 +200,81 @@ class TSInt128
|
||||
return static_cast<long double>(s128Value);
|
||||
}
|
||||
|
||||
inline operator int32_t() const
|
||||
{
|
||||
if (s128Value > static_cast<int128_t>(INT32_MAX))
|
||||
return INT32_MAX;
|
||||
if (s128Value < static_cast<int128_t>(INT32_MIN))
|
||||
return INT32_MIN;
|
||||
|
||||
return static_cast<int32_t>(s128Value);
|
||||
}
|
||||
|
||||
inline operator uint32_t() const
|
||||
{
|
||||
if (s128Value > static_cast<int128_t>(UINT32_MAX))
|
||||
return UINT32_MAX;
|
||||
if (s128Value < 0)
|
||||
return 0;
|
||||
|
||||
return static_cast<uint32_t>(s128Value);
|
||||
}
|
||||
|
||||
inline operator int64_t() const
|
||||
{
|
||||
if (s128Value > static_cast<int128_t>(INT64_MAX))
|
||||
return INT64_MAX;
|
||||
if (s128Value < static_cast<int128_t>(INT64_MIN))
|
||||
return INT64_MIN;
|
||||
|
||||
return static_cast<int64_t>(s128Value);
|
||||
}
|
||||
|
||||
inline operator uint64_t() const
|
||||
{
|
||||
if (s128Value > static_cast<int128_t>(UINT64_MAX))
|
||||
return UINT64_MAX;
|
||||
if (s128Value < 0)
|
||||
return 0;
|
||||
|
||||
return static_cast<uint64_t>(s128Value);
|
||||
}
|
||||
|
||||
inline operator TFloat128() const
|
||||
{
|
||||
return toTFloat128();
|
||||
}
|
||||
|
||||
inline TSInt128 operator%(const int64_t& rhs) const
|
||||
{
|
||||
return TSInt128(s128Value % rhs);
|
||||
}
|
||||
|
||||
inline TSInt128 operator%(const int128_t& rhs) const
|
||||
{
|
||||
return TSInt128(s128Value % rhs);
|
||||
}
|
||||
|
||||
inline TSInt128 operator*(const TSInt128& rhs) const
|
||||
{
|
||||
return TSInt128(s128Value * rhs.s128Value);
|
||||
}
|
||||
|
||||
inline TSInt128 operator+(const TSInt128& rhs) const
|
||||
{
|
||||
return TSInt128(s128Value + rhs.s128Value);
|
||||
}
|
||||
|
||||
inline TFloat128 toTFloat128() const
|
||||
{
|
||||
return TFloat128(s128Value);
|
||||
}
|
||||
|
||||
inline const int128_t& getValue() const
|
||||
{
|
||||
return s128Value;
|
||||
}
|
||||
|
||||
// print int128_t parts represented as PODs
|
||||
uint8_t printPodParts(char* buf,
|
||||
const int128_t& high,
|
||||
@ -226,19 +291,6 @@ class TSInt128
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const TSInt128& x);
|
||||
|
||||
// The method converts a wide decimal s128Value to an int64_t,
|
||||
// saturating the s128Value if necessary.
|
||||
inline int64_t getInt64FromWideDecimal();
|
||||
|
||||
// The method converts a wide decimal s128Value to an uint32_t.
|
||||
inline uint32_t getUInt32FromWideDecimal();
|
||||
|
||||
// The method converts a wide decimal s128Value to an uint64_t.
|
||||
inline uint64_t getUInt64FromWideDecimal();
|
||||
|
||||
// The method converts a wide decimal s128Value to an int32_t.
|
||||
inline int32_t getInt32FromWideDecimal();
|
||||
|
||||
int128_t s128Value;
|
||||
}; // end of class
|
||||
|
||||
|
@ -153,7 +153,7 @@ void SimpleColumn_Decimal<len>::setNullVal()
|
||||
template<int len>
|
||||
inline const std::string& SimpleColumn_Decimal<len>:: getStrVal(rowgroup::Row& row, bool& isNull)
|
||||
{
|
||||
datatypes::VDecimal dec((int64_t)row.getIntField<len>(fInputIndex),
|
||||
datatypes::Decimal dec((int64_t)row.getIntField<len>(fInputIndex),
|
||||
fResultType.scale,
|
||||
fResultType.precision);
|
||||
fResult.strVal = dec.toString();
|
||||
|
@ -55,24 +55,7 @@ namespace execplan
|
||||
{
|
||||
|
||||
typedef execplan::CalpontSystemCatalog::ColType Type;
|
||||
|
||||
|
||||
class IDB_Decimal: public datatypes::VDecimal
|
||||
{
|
||||
public:
|
||||
IDB_Decimal() = default;
|
||||
IDB_Decimal(int64_t val, int8_t s, uint8_t p, const int128_t &val128 = 0) :
|
||||
VDecimal(val, s, p, val128) {}
|
||||
|
||||
inline void operator=(const datatypes::TSInt128& rhs)
|
||||
{
|
||||
value = 0; scale = 0; precision = 0;
|
||||
datatypes::TSInt128::operator=(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef IDB_Decimal CNX_Decimal;
|
||||
typedef datatypes::Decimal IDB_Decimal;
|
||||
|
||||
/**
|
||||
* @brief IDB_Regex struct
|
||||
@ -728,13 +711,7 @@ inline int64_t TreeNode::getIntVal()
|
||||
{
|
||||
if (fResultType.colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t scaleDivisor;
|
||||
|
||||
datatypes::getScaleDivisor(scaleDivisor, fResult.decimalVal.scale);
|
||||
|
||||
int128_t tmpval = fResult.decimalVal.s128Value / scaleDivisor;
|
||||
|
||||
return datatypes::Decimal::getInt64FromWideDecimal(tmpval);
|
||||
return static_cast<int64_t>(fResult.decimalVal.getIntegralPart());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -460,7 +460,7 @@ void GroupConcator::outputRow(std::ostringstream& oss, const rowgroup::Row& row)
|
||||
|
||||
if (LIKELY(row.getColumnWidth(*i) == datatypes::MAXDECIMALWIDTH))
|
||||
{
|
||||
datatypes::VDecimal dec(0,
|
||||
datatypes::Decimal dec(0,
|
||||
scale,
|
||||
row.getPrecision(*i),
|
||||
row.getBinaryField<int128_t>(*i));
|
||||
|
@ -1188,7 +1188,7 @@ dec4: /* have to pick a scale to use for the double. using 5..
|
||||
{
|
||||
if (LIKELY(isInputWide))
|
||||
{
|
||||
datatypes::VDecimal dec(0,
|
||||
datatypes::Decimal dec(0,
|
||||
in.getScale(i),
|
||||
in.getPrecision(i),
|
||||
val128);
|
||||
@ -1196,7 +1196,7 @@ dec4: /* have to pick a scale to use for the double. using 5..
|
||||
}
|
||||
else
|
||||
{
|
||||
datatypes::VDecimal dec(val,
|
||||
datatypes::Decimal dec(val,
|
||||
in.getScale(i),
|
||||
in.getPrecision(i));
|
||||
out->setStringField(dec.toString(), i);
|
||||
|
@ -161,13 +161,13 @@ public:
|
||||
return m_field->store(static_cast<double>(dl));
|
||||
}
|
||||
|
||||
int store_decimal64(const datatypes::VDecimal& dec) override
|
||||
int store_decimal64(const datatypes::Decimal& dec) override
|
||||
{
|
||||
std::string decAsAStr = dec.toString();
|
||||
return m_field->store(decAsAStr.c_str(), decAsAStr.length(), m_field->charset());
|
||||
}
|
||||
|
||||
int store_decimal128(const datatypes::VDecimal& dec) override
|
||||
int store_decimal128(const datatypes::Decimal& dec) override
|
||||
{
|
||||
std::string decAsAStr = dec.toString(true);
|
||||
return m_field->store(decAsAStr.c_str(), decAsAStr.length(), m_field->charset());
|
||||
|
@ -908,7 +908,7 @@ TEST(Decimal, DecimalToStringCheckScale0)
|
||||
int precision = 38;
|
||||
int scale = 0;
|
||||
res = 0;
|
||||
datatypes::VDecimal dec(0, scale, precision, res);
|
||||
datatypes::Decimal dec(0, scale, precision, res);
|
||||
|
||||
// test simple values
|
||||
expected = "0";
|
||||
@ -957,7 +957,7 @@ TEST(Decimal, DecimalToStringCheckScale10)
|
||||
int precision = 38;
|
||||
int scale = 10;
|
||||
res = 0;
|
||||
datatypes::VDecimal dec(0, scale, precision, res);
|
||||
datatypes::Decimal dec(0, scale, precision, res);
|
||||
|
||||
// test simple values
|
||||
expected = "0.0000000000";
|
||||
@ -1029,7 +1029,7 @@ TEST(Decimal, DecimalToStringCheckScale38)
|
||||
int precision = 38;
|
||||
int scale = 38;
|
||||
res = 0;
|
||||
datatypes::VDecimal dec(0, scale, precision, res);
|
||||
datatypes::Decimal dec(0, scale, precision, res);
|
||||
|
||||
// test simple values
|
||||
res = 0;
|
||||
@ -1089,7 +1089,7 @@ TEST(Decimal, DecimalToStringCheckScale37)
|
||||
int precision = 38;
|
||||
int scale = 37;
|
||||
res = 0;
|
||||
datatypes::VDecimal dec(0, scale, precision, res);
|
||||
datatypes::Decimal dec(0, scale, precision, res);
|
||||
|
||||
// test simple values
|
||||
res = 0;
|
||||
|
@ -188,22 +188,7 @@ int64_t Func_cast_signed::getIntVal(Row& row,
|
||||
|
||||
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t scaleDivisor, scaleDivisor2;
|
||||
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
|
||||
scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10);
|
||||
|
||||
int128_t tmpval = d.s128Value / scaleDivisor;
|
||||
int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2;
|
||||
|
||||
if (tmpval >= 0 && lefto > 4)
|
||||
tmpval++;
|
||||
|
||||
if (tmpval < 0 && lefto < -4)
|
||||
tmpval--;
|
||||
|
||||
return datatypes::Decimal::getInt64FromWideDecimal(tmpval);
|
||||
return static_cast<int64_t>(d.getPosNegRoundedIntegralPart(4));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1206,13 +1191,7 @@ int64_t Func_cast_decimal::getIntVal(Row& row,
|
||||
|
||||
if (decimal.isTSInt128ByPrecision())
|
||||
{
|
||||
int128_t scaleDivisor;
|
||||
|
||||
datatypes::getScaleDivisor(scaleDivisor, decimal.scale);
|
||||
|
||||
int128_t tmpval = decimal.s128Value / scaleDivisor;
|
||||
|
||||
return datatypes::Decimal::getInt64FromWideDecimal(tmpval);
|
||||
return static_cast<int64_t>(decimal.getIntegralPart());
|
||||
}
|
||||
|
||||
return (int64_t) decimal.value / helpers::powerOf10_c[decimal.scale];
|
||||
|
@ -99,17 +99,7 @@ int64_t Func_ceil::getIntVal(Row& row,
|
||||
|
||||
if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t tmp = d.s128Value;
|
||||
int128_t scaleDivisor;
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
d.s128Value /= scaleDivisor;
|
||||
|
||||
// Add 1 if this is a positive number and there were values to the right of the
|
||||
// decimal point so that we return the largest integer value not less than X.
|
||||
if ((tmp - (d.s128Value * scaleDivisor)) > 0)
|
||||
d.s128Value += 1;
|
||||
|
||||
ret = datatypes::Decimal::getInt64FromWideDecimal(d.s128Value);
|
||||
ret = static_cast<int64_t>(d.getRoundedIntegralPart());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -252,17 +242,7 @@ uint64_t Func_ceil::getUintVal(Row& row,
|
||||
|
||||
if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t tmp = d.s128Value;
|
||||
int128_t scaleDivisor;
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
d.s128Value /= scaleDivisor;
|
||||
|
||||
// Add 1 if this is a positive number and there were values to the right of the
|
||||
// decimal point so that we return the largest integer value not less than X.
|
||||
if ((tmp - (d.s128Value * scaleDivisor)) > 0)
|
||||
d.s128Value += 1;
|
||||
|
||||
ret = datatypes::Decimal::getUInt64FromWideDecimal(d.s128Value);
|
||||
ret = static_cast<uint64_t>(d.getRoundedIntegralPart());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -548,6 +528,8 @@ IDB_Decimal Func_ceil::getDecimalVal(Row& row,
|
||||
bool& isNull,
|
||||
CalpontSystemCatalog::ColType& op_ct)
|
||||
{
|
||||
// Questionable approach. I believe we should use pointer here
|
||||
// and call an appropriate ctor
|
||||
IDB_Decimal ret;
|
||||
|
||||
switch (op_ct.colDataType)
|
||||
@ -583,15 +565,9 @@ IDB_Decimal Func_ceil::getDecimalVal(Row& row,
|
||||
|
||||
if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t tmp = ret.s128Value;
|
||||
int128_t scaleDivisor;
|
||||
datatypes::getScaleDivisor(scaleDivisor, ret.scale);
|
||||
ret.s128Value /= scaleDivisor;
|
||||
|
||||
// Add 1 if this is a positive number and there were values to the right of the
|
||||
// decimal point so that we return the largest integer value not less than X.
|
||||
if ((tmp - (ret.s128Value * scaleDivisor)) > 0)
|
||||
ret.s128Value += 1;
|
||||
ret = IDB_Decimal(ret.getRoundedIntegralPart(),
|
||||
ret.scale,
|
||||
ret.precision);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -138,33 +138,22 @@ string Func_char::getStrVal(Row& row,
|
||||
{
|
||||
IDB_Decimal d = rc->getDecimalVal(row, isNull);
|
||||
|
||||
uint8_t roundingFactor = 4;
|
||||
if (ct.colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
if (d.s128Value < 0)
|
||||
return "";
|
||||
|
||||
int128_t scaleDivisor, scaleDivisor2;
|
||||
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
|
||||
scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10);
|
||||
|
||||
int128_t tmpval = d.s128Value / scaleDivisor;
|
||||
int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2;
|
||||
|
||||
if (lefto > 4)
|
||||
tmpval++;
|
||||
|
||||
value = datatypes::Decimal::getInt32FromWideDecimal(tmpval);
|
||||
// rounding by the left over
|
||||
value = static_cast<int32_t>(d.getRoundedIntegralPart(roundingFactor));
|
||||
}
|
||||
else
|
||||
{
|
||||
double dscale = d.scale;
|
||||
// get decimal and round up
|
||||
value = d.value / pow(10.0, dscale);
|
||||
int lefto = (d.value - value * pow(10.0, dscale)) / pow(10.0, dscale - 1);
|
||||
uint8_t lefto = (d.value - value * pow(10.0, dscale)) / pow(10.0, dscale - 1);
|
||||
|
||||
if ( lefto > 4 )
|
||||
if ( lefto > roundingFactor )
|
||||
value++;
|
||||
}
|
||||
}
|
||||
|
@ -77,22 +77,7 @@ string Func_elt::getStrVal(rowgroup::Row& row,
|
||||
|
||||
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t scaleDivisor, scaleDivisor2;
|
||||
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
|
||||
scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10);
|
||||
|
||||
int128_t tmpval = d.s128Value / scaleDivisor;
|
||||
int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2;
|
||||
|
||||
if (utils::is_nonnegative(tmpval) && lefto > 4)
|
||||
tmpval++;
|
||||
|
||||
if (utils::is_negative(tmpval) && lefto < -4)
|
||||
tmpval--;
|
||||
|
||||
number = datatypes::Decimal::getInt64FromWideDecimal(tmpval);
|
||||
number = static_cast<int64_t>(d.getPosNegRoundedIntegralPart(4));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -160,7 +160,7 @@ int64_t Func_floor::getIntVal(Row& row,
|
||||
|
||||
if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
ret = datatypes::Decimal::getInt64FromWideDecimal(tmp.s128Value);
|
||||
ret = static_cast<int64_t>(tmp.toTSInt128());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -67,10 +67,9 @@ DateTime getDateTime(rowgroup::Row& row,
|
||||
|
||||
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t scaleDivisor;
|
||||
datatypes::getScaleDivisor(scaleDivisor, dec.scale);
|
||||
val = datatypes::Decimal::getInt64FromWideDecimal(dec.s128Value / scaleDivisor);
|
||||
msec = datatypes::Decimal::getUInt32FromWideDecimal(dec.s128Value % scaleDivisor);
|
||||
auto integralAndFractional = dec.getIntegralAndFractional();
|
||||
val = static_cast<int64_t>(integralAndFractional.first);
|
||||
msec = static_cast<uint32_t>(integralAndFractional.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -72,22 +72,7 @@ uint64_t makedate(rowgroup::Row& row,
|
||||
|
||||
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t scaleDivisor, scaleDivisor2;
|
||||
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
|
||||
scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10);
|
||||
|
||||
int128_t tmpval = d.s128Value / scaleDivisor;
|
||||
int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2;
|
||||
|
||||
if (tmpval >= 0 && lefto > 4)
|
||||
tmpval++;
|
||||
|
||||
if (tmpval < 0 && lefto < -4)
|
||||
tmpval--;
|
||||
|
||||
year = datatypes::Decimal::getInt64FromWideDecimal(tmpval);
|
||||
year = static_cast<int64_t>(d.getPosNegRoundedIntegralPart(4));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -156,29 +141,14 @@ uint64_t makedate(rowgroup::Row& row,
|
||||
|
||||
if (parm[1]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t scaleDivisor, scaleDivisor2;
|
||||
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
|
||||
scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10);
|
||||
|
||||
int128_t tmpval = d.s128Value / scaleDivisor;
|
||||
int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2;
|
||||
|
||||
if (tmpval >= 0 && lefto > 4)
|
||||
tmpval++;
|
||||
|
||||
if (tmpval < 0 && lefto < -4)
|
||||
tmpval--;
|
||||
|
||||
int64_t tmpval = static_cast<int64_t>(d.getPosNegRoundedIntegralPart(4));
|
||||
if (tmpval < 1)
|
||||
{
|
||||
isNull = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t tmpval64 = datatypes::Decimal::getInt64FromWideDecimal(tmpval);
|
||||
dayofyear = helpers::intToString(tmpval64);
|
||||
dayofyear = helpers::intToString(tmpval);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -78,22 +78,7 @@ string Func_maketime::getStrVal(rowgroup::Row& row,
|
||||
|
||||
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t scaleDivisor, scaleDivisor2;
|
||||
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
|
||||
scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10);
|
||||
|
||||
int128_t tmpval = d.s128Value / scaleDivisor;
|
||||
int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2;
|
||||
|
||||
if (tmpval >= 0 && lefto > 4)
|
||||
tmpval++;
|
||||
|
||||
if (tmpval < 0 && lefto < -4)
|
||||
tmpval--;
|
||||
|
||||
hour = datatypes::Decimal::getInt64FromWideDecimal(tmpval);
|
||||
hour = static_cast<int64_t>(d.getPosNegRoundedIntegralPart(4));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -142,22 +127,7 @@ string Func_maketime::getStrVal(rowgroup::Row& row,
|
||||
|
||||
if (parm[1]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t scaleDivisor, scaleDivisor2;
|
||||
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
|
||||
scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10);
|
||||
|
||||
int128_t tmpval = d.s128Value / scaleDivisor;
|
||||
int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2;
|
||||
|
||||
if (tmpval >= 0 && lefto > 4)
|
||||
tmpval++;
|
||||
|
||||
if (tmpval < 0 && lefto < -4)
|
||||
tmpval--;
|
||||
|
||||
min = datatypes::Decimal::getInt64FromWideDecimal(tmpval);
|
||||
min = static_cast<int64_t>(d.getPosNegRoundedIntegralPart(4));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -212,22 +182,7 @@ string Func_maketime::getStrVal(rowgroup::Row& row,
|
||||
|
||||
if (parm[2]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
int128_t scaleDivisor, scaleDivisor2;
|
||||
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
|
||||
scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10);
|
||||
|
||||
int128_t tmpval = d.s128Value / scaleDivisor;
|
||||
int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2;
|
||||
|
||||
if (tmpval >= 0 && lefto > 4)
|
||||
tmpval++;
|
||||
|
||||
if (tmpval < 0 && lefto < -4)
|
||||
tmpval--;
|
||||
|
||||
sec = datatypes::Decimal::getInt64FromWideDecimal(tmpval);
|
||||
sec = static_cast<int64_t>(d.getPosNegRoundedIntegralPart(4));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -56,59 +56,40 @@ IDB_Decimal Func_mod::getDecimalVal(Row& row,
|
||||
bool& isNull,
|
||||
CalpontSystemCatalog::ColType& operationColType)
|
||||
{
|
||||
IDB_Decimal retValue;
|
||||
retValue.value = 0;
|
||||
retValue.scale = 0;
|
||||
|
||||
if ( parm.size() < 2 )
|
||||
{
|
||||
isNull = true;
|
||||
return retValue;
|
||||
return IDB_Decimal();
|
||||
}
|
||||
|
||||
if (parm[0]->data()->resultType().isWideDecimalType() ||
|
||||
parm[1]->data()->resultType().isWideDecimalType())
|
||||
{
|
||||
IDB_Decimal div = parm[1]->data()->getDecimalVal(row, isNull);
|
||||
|
||||
int128_t divInt, dividendInt;
|
||||
|
||||
if (parm[1]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
divInt = div.s128Value;
|
||||
else
|
||||
divInt = div.value;
|
||||
int128_t divInt = (parm[1]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) ? div.s128Value : div.value;
|
||||
|
||||
if (divInt == 0)
|
||||
{
|
||||
isNull = true;
|
||||
return retValue;
|
||||
return IDB_Decimal();
|
||||
}
|
||||
|
||||
IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull);
|
||||
|
||||
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
dividendInt = d.s128Value;
|
||||
else
|
||||
dividendInt = d.value;
|
||||
|
||||
// integer division
|
||||
if (d.scale == 0 && div.scale == 0)
|
||||
// two special cases: both Decimals has no scale
|
||||
// or divisor has no scale
|
||||
if (!div.isScaled())
|
||||
{
|
||||
retValue.s128Value = dividendInt % divInt;
|
||||
}
|
||||
// special case integer division
|
||||
else if (div.scale == 0)
|
||||
{
|
||||
int128_t scaleDivisor;
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
int128_t value = dividendInt / scaleDivisor;
|
||||
int128_t lefto = dividendInt % scaleDivisor;
|
||||
int128_t mod = (value % divInt) * scaleDivisor + lefto;
|
||||
retValue.s128Value = mod;
|
||||
return IDB_Decimal(d % div.toTSInt128(),
|
||||
d.scale,
|
||||
datatypes::INT128MAXPRECISION);
|
||||
}
|
||||
// float division
|
||||
else
|
||||
{
|
||||
int128_t dividendInt = (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) ? d.s128Value : d.value;
|
||||
|
||||
|
||||
__float128 divF, dividendF;
|
||||
|
||||
int128_t scaleDivisor;
|
||||
@ -121,19 +102,17 @@ IDB_Decimal Func_mod::getDecimalVal(Row& row,
|
||||
|
||||
__float128 mod = fmodq(dividendF, divF) * scaleDivisor;
|
||||
|
||||
retValue.s128Value = (int128_t) mod;
|
||||
return IDB_Decimal(datatypes::TSInt128((int128_t) mod),
|
||||
d.scale,
|
||||
datatypes::INT128MAXPRECISION);
|
||||
}
|
||||
retValue.scale = d.scale;
|
||||
retValue.precision = datatypes::INT128MAXPRECISION;
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t div = parm[1]->data()->getIntVal(row, isNull);
|
||||
|
||||
if ( div == 0 )
|
||||
{
|
||||
isNull = true;
|
||||
return retValue;
|
||||
return IDB_Decimal();
|
||||
}
|
||||
|
||||
IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull);
|
||||
@ -141,12 +120,8 @@ IDB_Decimal Func_mod::getDecimalVal(Row& row,
|
||||
int lefto = d.value % (int)pow(10.0, d.scale);
|
||||
|
||||
int64_t mod = (value % div) * pow(10.0, d.scale) + lefto;
|
||||
|
||||
retValue.value = mod;
|
||||
retValue.scale = d.scale;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
// It is misterious but precision is set to 0!
|
||||
return IDB_Decimal(mod, d.scale, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -227,29 +202,7 @@ double Func_mod::getDoubleVal(Row& row,
|
||||
case execplan::CalpontSystemCatalog::DECIMAL:
|
||||
case execplan::CalpontSystemCatalog::UDECIMAL:
|
||||
{
|
||||
IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull);
|
||||
|
||||
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
if (d.scale == 0)
|
||||
{
|
||||
mod = d.s128Value % div;
|
||||
}
|
||||
else
|
||||
{
|
||||
int128_t scaleDivisor;
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
int128_t value = d.s128Value / scaleDivisor;
|
||||
int128_t lefto = d.s128Value % scaleDivisor;
|
||||
datatypes::TFloat128 tmp((__float128) (value % div) + (__float128) lefto / scaleDivisor);
|
||||
mod = static_cast<double>(tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t value = d.value / pow(10.0, d.scale);
|
||||
mod = value % div;
|
||||
}
|
||||
mod = doDecimal<decltype(mod)>(parm, div, row, isNull);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -350,29 +303,7 @@ long double Func_mod::getLongDoubleVal(Row& row,
|
||||
case execplan::CalpontSystemCatalog::DECIMAL:
|
||||
case execplan::CalpontSystemCatalog::UDECIMAL:
|
||||
{
|
||||
IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull);
|
||||
|
||||
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
if (d.scale == 0)
|
||||
{
|
||||
mod = d.s128Value % div;
|
||||
}
|
||||
else
|
||||
{
|
||||
int128_t scaleDivisor;
|
||||
datatypes::getScaleDivisor(scaleDivisor, d.scale);
|
||||
int128_t value = d.s128Value / scaleDivisor;
|
||||
int128_t lefto = d.s128Value % scaleDivisor;
|
||||
datatypes::TFloat128 tmp((__float128) (value % div) + (__float128) lefto / scaleDivisor);
|
||||
mod = static_cast<long double>(tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t value = d.value / pow(10.0, d.scale);
|
||||
mod = value % div;
|
||||
}
|
||||
mod = doDecimal<decltype(mod)>(parm, div, row, isNull);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -476,29 +407,7 @@ int64_t Func_mod::getIntVal(Row& row,
|
||||
case execplan::CalpontSystemCatalog::DECIMAL:
|
||||
case execplan::CalpontSystemCatalog::UDECIMAL:
|
||||
{
|
||||
IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull);
|
||||
|
||||
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
if (d.scale == 0)
|
||||
{
|
||||
mod = d.s128Value % div;
|
||||
}
|
||||
else
|
||||
{
|
||||
int128_t scaleDivisor;
|
||||
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::Decimal::getInt64FromFloat128(tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t value = d.value / pow(10.0, d.scale);
|
||||
mod = value % div;
|
||||
}
|
||||
mod = doDecimal<decltype(mod)>(parm, div, row, isNull);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -593,29 +502,7 @@ uint64_t Func_mod::getUIntVal(Row& row,
|
||||
case execplan::CalpontSystemCatalog::DECIMAL:
|
||||
case execplan::CalpontSystemCatalog::UDECIMAL:
|
||||
{
|
||||
IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull);
|
||||
|
||||
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
if (d.scale == 0)
|
||||
{
|
||||
mod = d.s128Value % div;
|
||||
}
|
||||
else
|
||||
{
|
||||
int128_t scaleDivisor;
|
||||
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::Decimal::getUInt64FromFloat128(tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t value = d.value / pow(10.0, d.scale);
|
||||
mod = value % div;
|
||||
}
|
||||
mod = doDecimal<decltype(mod)>(parm, div, row, isNull);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -133,18 +133,7 @@ int64_t Func_round::getIntVal(Row& row,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x.scale > 0)
|
||||
{
|
||||
while (x.scale-- > 0)
|
||||
x.s128Value /= 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (x.scale++ < 0)
|
||||
x.s128Value *= 10;
|
||||
}
|
||||
|
||||
return datatypes::Decimal::getInt64FromWideDecimal(x.s128Value);
|
||||
return static_cast<int64_t>(x.getIntegralPart());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,18 +136,7 @@ int64_t Func_truncate::getIntVal(Row& row,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x.scale > 0)
|
||||
{
|
||||
while (x.scale-- > 0)
|
||||
x.s128Value /= 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (x.scale++ < 0)
|
||||
x.s128Value *= 10;
|
||||
}
|
||||
|
||||
return datatypes::Decimal::getInt64FromWideDecimal(x.s128Value);
|
||||
return static_cast<int64_t>(x.getIntegralPart());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,6 +427,35 @@ public:
|
||||
FunctionParm& fp,
|
||||
bool& isNull,
|
||||
execplan::CalpontSystemCatalog::ColType& op_ct);
|
||||
private:
|
||||
template<typename ModType>
|
||||
ModType doDecimal(const FunctionParm& parm,
|
||||
const int64_t div,
|
||||
rowgroup::Row& row,
|
||||
bool isNull)
|
||||
{
|
||||
execplan::IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull);
|
||||
|
||||
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
if (!d.isScaled())
|
||||
{
|
||||
return d.toTSInt128() % div;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto intAndFract = d.getIntegralAndDividedFractional();
|
||||
|
||||
datatypes::TSInt128 integralRemainder = intAndFract.first % div;
|
||||
return static_cast<ModType>(integralRemainder.toTFloat128() +
|
||||
intAndFract.second);
|
||||
|
||||
}
|
||||
}
|
||||
int64_t value = d.value / pow(10.0, d.scale);
|
||||
return value % div;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -637,7 +637,7 @@ string Row::toString() const
|
||||
case CalpontSystemCatalog::UDECIMAL:
|
||||
if (colWidths[i] == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
datatypes::VDecimal dec(0,
|
||||
datatypes::Decimal dec(0,
|
||||
scale[i],
|
||||
precision[i],
|
||||
getBinaryField<int128_t>(i));
|
||||
|
@ -2994,7 +2994,7 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs,
|
||||
{
|
||||
if (fetchColColwidths[fetchColPos] == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
datatypes::VDecimal dec(0,
|
||||
datatypes::Decimal dec(0,
|
||||
fetchColScales[fetchColPos],
|
||||
rowGroups[txnId]->getPrecision()[fetchColPos],
|
||||
row.getBinaryField<int128_t>(fetchColPos));
|
||||
@ -3037,7 +3037,7 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs,
|
||||
}
|
||||
else
|
||||
{
|
||||
datatypes::VDecimal dec(intColVal,
|
||||
datatypes::Decimal dec(intColVal,
|
||||
fetchColScales[fetchColPos],
|
||||
rowGroups[txnId]->getPrecision()[fetchColPos]);
|
||||
value = dec.toString();
|
||||
@ -3349,7 +3349,7 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs,
|
||||
{
|
||||
if (fetchColColwidths[fetchColPos] == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
datatypes::VDecimal dec(0,
|
||||
datatypes::Decimal dec(0,
|
||||
fetchColScales[fetchColPos],
|
||||
rowGroups[txnId]->getPrecision()[fetchColPos],
|
||||
row.getBinaryField<int128_t>(fetchColPos));
|
||||
@ -3393,7 +3393,7 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs,
|
||||
}
|
||||
else
|
||||
{
|
||||
datatypes::VDecimal dec(intColVal,
|
||||
datatypes::Decimal dec(intColVal,
|
||||
fetchColScales[fetchColPos],
|
||||
rowGroups[txnId]->getPrecision()[fetchColPos]);
|
||||
value = dec.toString();
|
||||
|
Reference in New Issue
Block a user