1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-08-01 06:46:55 +03:00

MCOL-4478 MCS now rounds the last digits of an avg() result for wide-DECIMAL argument

This commit is contained in:
Roman Nozdrin
2020-12-30 11:35:51 +00:00
parent cf11e03d4b
commit 5b9689ce55
4 changed files with 40 additions and 23 deletions

View File

@ -22,24 +22,6 @@
namespace datatypes
{
struct lldiv_t_128
{
int128_t quot;
int128_t rem;
lldiv_t_128() : quot(0), rem(0) {}
lldiv_t_128(const int128_t& a_quot, const int128_t& a_rem)
: quot(a_quot), rem(a_rem) {}
};
inline lldiv_t_128 lldiv128(const int128_t& dividend, const int128_t& divisor)
{
if (UNLIKELY(divisor == 0) || UNLIKELY(dividend == 0))
return lldiv_t_128();
return lldiv_t_128(dividend / divisor, dividend % divisor);
}
template<typename BinaryOperation,
typename OpOverflowCheck,
typename MultiplicationOverflowCheck>
@ -115,7 +97,6 @@ namespace datatypes
? r.s128Value : r.value;
opOverflowCheck(lValue, rValue);
if (result.scale >= l.scale - r.scale)
{
int128_t scaleMultiplier;
@ -213,7 +194,7 @@ namespace datatypes
// rem carries the value's sign, but needs to be normalized.
int64_t s = l.scale - r.scale;
int128_t divisor;
getScaleDivisor(divisor, abs(s));
getScaleDivisor(divisor, std::abs(s));
if (s < 0)
{

View File

@ -161,6 +161,23 @@ inline void getScaleDivisor(T& divisor, const int8_t scale)
}
}
struct lldiv_t_128
{
int128_t quot;
int128_t rem;
lldiv_t_128() : quot(0), rem(0) {}
lldiv_t_128(const int128_t& a_quot, const int128_t& a_rem)
: quot(a_quot), rem(a_rem) {}
};
inline lldiv_t_128 lldiv128(const int128_t& dividend, const int128_t& divisor)
{
if (UNLIKELY(divisor == 0) || UNLIKELY(dividend == 0))
return lldiv_t_128();
return lldiv_t_128(dividend / divisor, dividend % divisor);
}
// @brief The class for Decimal related operations
// The class contains Decimal related operations are scale and
// precision aware.

View File

@ -112,6 +112,11 @@ struct is_uint128_t<uint128_t> {
static const bool value = true;
};
inline int128_t abs(int128_t& x)
{
return (x >= 0) ? x : -x;
}
class TSInt128
{
public:

View File

@ -2800,8 +2800,22 @@ void RowAggregationUM::calculateAvgColumns()
multOp(*sumPnt, datatypes::mcs_pow_10[scaleDiff], sum);
else
sum = *sumPnt;
int128_t avg = sum / cnt;
fRow.setBinaryField_offset(&avg, sizeof(avg), offset);
datatypes::lldiv_t_128 avgAndRem = datatypes::lldiv128(sum, cnt);
// Round the last digit
if (datatypes::abs(avgAndRem.rem) * 2 >= (int128_t)cnt)
{
if (utils::is_negative(avgAndRem.rem))
{
avgAndRem.quot--;
}
else
{
avgAndRem.quot++;
}
}
fRow.setBinaryField_offset(&avgAndRem.quot,
sizeof(avgAndRem.quot),
offset);
}
}
}