You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-29 08:21:15 +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
|
||||
|
||||
|
Reference in New Issue
Block a user