1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-30 19:23:07 +03:00

Merge pull request #1856 from mariadb-corporation/bar-develop-MCOL-4361

MCOL-4361 Replace pow(10.0, (double)scale) expressions with a static …
This commit is contained in:
Gagan Goel
2021-04-13 07:01:33 -04:00
committed by GitHub
13 changed files with 153 additions and 132 deletions

View File

@ -195,6 +195,14 @@ public:
}; };
template<typename T>
T applySignedScale(const T & val, int32_t scale)
{
return scale < 0 ?
val / datatypes::scaleDivisor<T>((uint32_t) -scale) :
val * datatypes::scaleDivisor<T>((uint32_t) scale);
}
/** /**
@brief The function to produce scale multiplier/divisor for @brief The function to produce scale multiplier/divisor for
wide decimals. wide decimals.
@ -267,6 +275,14 @@ public:
{ {
return DecomposedDecimal<int64_t>(value, scale).toSIntCeil(); return DecomposedDecimal<int64_t>(value, scale).toSIntCeil();
} }
// Convert to an arbitrary floating point data type,
// e.g. float, double, long double
template<typename T>
T toXFloat(uint32_t scale) const
{
return (T) value / scaleDivisor<T>(scale);
}
}; };
@ -590,6 +606,11 @@ class Decimal: public TDecimal128, public TDecimal64
return TDecimal64::toUInt64Round((uint32_t) scale); return TDecimal64::toUInt64Round((uint32_t) scale);
} }
template<typename T> T decimal64ToXFloat() const
{
return TDecimal64::toXFloat<T>((uint32_t) scale);
}
int64_t toSInt64Round() const int64_t toSInt64Round() const
{ {
return isWideDecimalTypeByPrecision(precision) ? return isWideDecimalTypeByPrecision(precision) ?

View File

@ -166,7 +166,9 @@ inline int64_t SimpleColumn_Decimal<len>:: getIntVal(rowgroup::Row& row, bool& i
if (row.equals<len>(fNullVal, fInputIndex)) if (row.equals<len>(fNullVal, fInputIndex))
isNull = true; isNull = true;
return (int64_t)(row.getIntField<len>(fInputIndex) / pow((double)10, fResultType.scale)); // TODO: fix double division to integer division
return (int64_t)(row.getIntField<len>(fInputIndex) /
datatypes::scaleDivisor<double>(fResultType.scale));
} }
template<int len> template<int len>
@ -175,7 +177,8 @@ inline float SimpleColumn_Decimal<len>::getFloatVal(rowgroup::Row& row, bool& is
if (row.equals<len>(fNullVal, fInputIndex)) if (row.equals<len>(fNullVal, fInputIndex))
isNull = true; isNull = true;
return (row.getIntField<len>(fInputIndex) / pow((double)10, fResultType.scale)); return (row.getIntField<len>(fInputIndex) /
datatypes::scaleDivisor<double>(fResultType.scale));
} }
template<int len> template<int len>
@ -184,7 +187,8 @@ inline double SimpleColumn_Decimal<len>::getDoubleVal(rowgroup::Row& row, bool&
if (row.equals<len>(fNullVal, fInputIndex)) if (row.equals<len>(fNullVal, fInputIndex))
isNull = true; isNull = true;
return (row.getIntField<len>(fInputIndex) / pow((double)10, fResultType.scale)); return (row.getIntField<len>(fInputIndex) /
datatypes::scaleDivisor<double>(fResultType.scale));
} }
template<int len> template<int len>
@ -193,7 +197,8 @@ inline long double SimpleColumn_Decimal<len>::getLongDoubleVal(rowgroup::Row& ro
if (row.equals<len>(fNullVal, fInputIndex)) if (row.equals<len>(fNullVal, fInputIndex))
isNull = true; isNull = true;
return (row.getIntField<len>(fInputIndex) / pow((double)10, fResultType.scale)); return (row.getIntField<len>(fInputIndex) /
datatypes::scaleDivisor<long double>(fResultType.scale));
} }
template<int len> template<int len>

View File

@ -828,7 +828,7 @@ inline float TreeNode::getFloatVal()
} }
else else
{ {
return (fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale)); return (float) fResult.decimalVal.decimal64ToXFloat<double>();
} }
} }
@ -903,8 +903,7 @@ inline double TreeNode::getDoubleVal()
} }
else else
{ {
// this may not be accurate. if this is problematic, change to pre-calculated power array. return fResult.decimalVal.decimal64ToXFloat<double>();
return (double)(fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
} }
} }
@ -979,8 +978,7 @@ inline long double TreeNode::getLongDoubleVal()
} }
else else
{ {
// this may not be accurate. if this is problematic, change to pre-calculated power array. return fResult.decimalVal.decimal64ToXFloat<long double>();
return (long double)(fResult.decimalVal.value / pow((long double)10, fResult.decimalVal.scale));
} }
} }

View File

@ -479,45 +479,22 @@ void TupleUnion::normalize(const Row& in, Row* out)
case CalpontSystemCatalog::FLOAT: case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT: case CalpontSystemCatalog::UFLOAT:
{ {
int scale = in.getScale(i); auto d = in.getScaledSInt64FieldAsXFloat<double>(i);
out->setFloatField((float) d, i);
if (scale != 0)
{
float f = in.getIntField(i);
f /= (uint64_t) pow(10.0, scale);
out->setFloatField(f, i);
}
else
out->setFloatField(in.getIntField(i), i);
break; break;
} }
case CalpontSystemCatalog::DOUBLE: case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE: case CalpontSystemCatalog::UDOUBLE:
{ {
int scale = in.getScale(i); auto d = in.getScaledSInt64FieldAsXFloat<double>(i);
out->setDoubleField(d, i);
if (scale != 0)
{
double d = in.getIntField(i);
d /= (uint64_t) pow(10.0, scale);
out->setDoubleField(d, i);
}
else
out->setDoubleField(in.getIntField(i), i);
break; break;
} }
case CalpontSystemCatalog::LONGDOUBLE: case CalpontSystemCatalog::LONGDOUBLE:
{ {
int scale = in.getScale(i); auto d = in.getScaledSInt64FieldAsXFloat<long double>(i);
long double d = in.getIntField(i);
if (scale != 0)
{
d /= (uint64_t) pow(10.0, scale);
}
out->setLongDoubleField(d, i); out->setLongDoubleField(d, i);
break; break;
} }
@ -526,13 +503,30 @@ void TupleUnion::normalize(const Row& in, Row* out)
case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UDECIMAL:
{ {
dec1: dec1:
uint64_t val = in.getIntField(i);
int diff = out->getScale(i) - in.getScale(i); int diff = out->getScale(i) - in.getScale(i);
/*
if (diff < 0) Signed INT to XDecimal
val /= (uint64_t) pow((double) 10, (double) - diff); TODO: there are a few problems here:
else - This code is not wide decimal friendly.
val *= (uint64_t) pow((double) 10, (double) diff); `uint64_t val` can overflow when applying a positive scale
It's not possible to make a reproducible bug report
at the moment: MCOL-4612 and MCOL-4613 should be fixed first.
- Using uint64_t is wrong here. The data type of "in" field is
signed. In case of a negative diff, the result will be wrong,
because division (unlike multiplication) is sensitive to
the signess of the operands.
Perhaps diff cannot be negative and we can put an assert for it.
Anyway, it's safer to change `uint64_t val` to `int64_t val`.
- This code does not handle overflow that may happen on
scale multiplication (MCOL-4613). Instead of returning a garbage
we should probably apply saturation here. In long terms we
should implement DECIMAL(65,x) to avoid overflow completely
(so the UNION between DECIMAL and integer can choose a proper
DECIMAL(M,N) result data type to guarantee that any incoming
integer value can fit into it).
*/
// TODO: isn't overflow possible below?
uint64_t val = datatypes::applySignedScale<uint64_t>(in.getIntField(i), diff);
if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH)
out->setInt128Field(val, i); out->setInt128Field(val, i);
@ -606,50 +600,23 @@ dec1:
case CalpontSystemCatalog::FLOAT: case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT: case CalpontSystemCatalog::UFLOAT:
{ {
int scale = in.getScale(i); auto d = in.getScaledUInt64FieldAsXFloat<double>(i);
out->setFloatField((float) d, i);
if (scale != 0)
{
float f = in.getUintField(i);
f /= (uint64_t) pow(10.0, scale);
out->setFloatField(f, i);
}
else
out->setFloatField(in.getUintField(i), i);
break; break;
} }
case CalpontSystemCatalog::DOUBLE: case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE: case CalpontSystemCatalog::UDOUBLE:
{ {
int scale = in.getScale(i); auto d = in.getScaledUInt64FieldAsXFloat<double>(i);
out->setDoubleField(d, i);
if (scale != 0)
{
double d = in.getUintField(i);
d /= (uint64_t) pow(10.0, scale);
out->setDoubleField(d, i);
}
else
out->setDoubleField(in.getUintField(i), i);
break; break;
} }
case CalpontSystemCatalog::LONGDOUBLE: case CalpontSystemCatalog::LONGDOUBLE:
{ {
int scale = in.getScale(i); auto d = in.getScaledUInt64FieldAsXFloat<long double>(i);
out->setLongDoubleField(d, i);
if (scale != 0)
{
long double d = in.getUintField(i);
d /= (uint64_t) pow(10.0, scale);
out->setLongDoubleField(d, i);
}
else
out->setLongDoubleField(in.getUintField(i), i);
break; break;
} }
@ -657,13 +624,16 @@ dec1:
case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UDECIMAL:
{ {
dec2: dec2:
uint64_t val = in.getIntField(i);
int diff = out->getScale(i) - in.getScale(i); int diff = out->getScale(i) - in.getScale(i);
/*
if (diff < 0) Unsigned INT to XDecimal
val /= (uint64_t) pow((double) 10, (double) - diff); TODO: There are a few problems here:
else - It should use in.getUintField() instead of in.getIntField()
val *= (uint64_t) pow((double) 10, (double) diff); - All problems mentioned in the code under label "dec1:" are
also applicable here.
*/
// TODO: isn't overflow possible below?
uint64_t val = datatypes::applySignedScale<uint64_t>(in.getIntField(i), diff);
if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH)
out->setInt128Field(val, i); out->setInt128Field(val, i);
@ -989,13 +959,15 @@ dec2:
{ {
dec3: /* have to pick a scale to use for the double. using 5... */ dec3: /* have to pick a scale to use for the double. using 5... */
uint32_t scale = 5; uint32_t scale = 5;
uint64_t ival = (uint64_t) (double) (val * pow((double) 10, (double) scale)); uint64_t ival = (uint64_t) (double) (val * datatypes::scaleDivisor<double>(scale));
int diff = out->getScale(i) - scale; int diff = out->getScale(i) - scale;
// xFLOAT or xDOUBLE to xDECIMAL conversion. Is it really possible?
if (diff < 0) // TODO:
ival /= (uint64_t) pow((double) 10, (double) - diff); // Perhaps we should add an assert here that this combination is not possible
else // In the current reduction all problems mentioned in the code under
ival *= (uint64_t) pow((double) 10, (double) diff); // label "dec1:" are also applicable here.
// TODO: isn't overflow possible below?
ival = datatypes::applySignedScale<uint64_t>(ival, diff);
if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH)
out->setInt128Field(ival, i); out->setInt128Field(ival, i);
@ -1070,13 +1042,15 @@ dec3: /* have to pick a scale to use for the double. using 5..
{ {
dec4: /* have to pick a scale to use for the double. using 5... */ dec4: /* have to pick a scale to use for the double. using 5... */
uint32_t scale = 5; uint32_t scale = 5;
uint64_t ival = (uint64_t) (double) (val * pow((double) 10, (double) scale)); uint64_t ival = (uint64_t) (double) (val * datatypes::scaleDivisor<double>(scale));
int diff = out->getScale(i) - scale; int diff = out->getScale(i) - scale;
if (diff < 0) // LONGDOUBLE to xDECIMAL conversions: is it really possible?
ival /= (uint64_t) pow((double) 10, (double) - diff); // TODO:
else // Perhaps we should add an assert here that this combination is not possible
ival *= (uint64_t) pow((double) 10, (double) diff); // In the current reduction all problems mentioned in the code under
// label "dec1:" are also applicable here.
ival = datatypes::applySignedScale<uint64_t>(ival, diff);
if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH)
out->setInt128Field(ival, i); out->setInt128Field(ival, i);

View File

@ -4463,8 +4463,8 @@ ConstantColumn* buildDecimalColumn(Item* item, gp_walk_info& gwi)
if (gwi.internalDecimalScale >= 0 && idp->decimals > (uint)gwi.internalDecimalScale) if (gwi.internalDecimalScale >= 0 && idp->decimals > (uint)gwi.internalDecimalScale)
{ {
columnstore_decimal.scale = gwi.internalDecimalScale; columnstore_decimal.scale = gwi.internalDecimalScale;
double val = (double)(columnstore_decimal.value / pow((double)10, idp->decimals - gwi.internalDecimalScale)); uint32_t diff = (uint32_t) (idp->decimals - gwi.internalDecimalScale);
columnstore_decimal.value = (int64_t)(val > 0 ? val + 0.5 : val - 0.5); columnstore_decimal.value= columnstore_decimal.TDecimal64::toSInt64Round(diff);
} }
else else
columnstore_decimal.scale = idp->decimal_scale(); columnstore_decimal.scale = idp->decimal_scale();

View File

@ -97,8 +97,8 @@ Command* FilterCommand::makeFilterCommand(ByteStream& bs, vector<SCommand>& cmds
ColumnCommand* cmd0 = dynamic_cast<ColumnCommand*>(cmds[nc - 2].get()); ColumnCommand* cmd0 = dynamic_cast<ColumnCommand*>(cmds[nc - 2].get());
ColumnCommand* cmd1 = dynamic_cast<ColumnCommand*>(cmds[nc - 1].get()); ColumnCommand* cmd1 = dynamic_cast<ColumnCommand*>(cmds[nc - 1].get());
int scale0 = cmd0->getScale(); uint32_t scale0 = cmd0->getScale();
int scale1 = cmd1->getScale(); uint32_t scale1 = cmd1->getScale();
// char[] is stored as int, but cannot directly compare if length is different // char[] is stored as int, but cannot directly compare if length is different
// due to endian issue // due to endian issue
@ -117,7 +117,8 @@ Command* FilterCommand::makeFilterCommand(ByteStream& bs, vector<SCommand>& cmds
else else
{ {
ScaledFilterCmd* sc = new ScaledFilterCmd(); ScaledFilterCmd* sc = new ScaledFilterCmd();
sc->setFactor(pow(10.0, scale1) / pow(10.0, scale0)); sc->setFactor(datatypes::scaleDivisor<double>(scale1) /
datatypes::scaleDivisor<double>(scale0));
fc = sc; fc = sc;
} }

View File

@ -1519,7 +1519,7 @@ double Func_cast_decimal::getDoubleVal(Row& row,
return static_cast<double>(decimal); return static_cast<double>(decimal);
} }
return (double) decimal.value / helpers::powerOf10_c[decimal.scale]; return decimal.decimal64ToXFloat<double>();
} }
@ -1631,7 +1631,7 @@ double Func_cast_double::getDoubleVal(Row& row,
} }
else else
{ {
dblval = (double)(decimal.value / pow((double)10, decimal.scale)); dblval = decimal.decimal64ToXFloat<double>();
} }
} }
break; break;

View File

@ -248,7 +248,7 @@ mcsv1_UDAF::ReturnCode Moda_impl_T<T>::nextValue(mcsv1Context* context, ColumnDa
if (val != 0 && scale > 0) if (val != 0 && scale > 0)
{ {
val /= pow(10.0, (double)scale); val /= datatypes::scaleDivisor<double>(scale);
} }
} }

View File

@ -1458,12 +1458,8 @@ void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int
} }
else if (width <= datatypes::MAXLEGACYWIDTH) else if (width <= datatypes::MAXLEGACYWIDTH)
{ {
valIn = rowIn.getIntField(colIn); uint32_t scale = fRowGroupIn.getScale()[colIn];
double scale = (double)(fRowGroupIn.getScale())[colIn]; valIn = rowIn.getScaledSInt64FieldAsXFloat<long double>(colIn, scale);
if (valIn != 0 && scale > 0)
{
valIn /= pow(10.0, scale);
}
} }
else else
{ {
@ -1938,12 +1934,8 @@ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int6
} }
else if (width <= datatypes::MAXLEGACYWIDTH) else if (width <= datatypes::MAXLEGACYWIDTH)
{ {
valIn = rowIn.getIntField(colIn); uint32_t scale = fRowGroupIn.getScale()[colIn];
double scale = (double)(fRowGroupIn.getScale())[colIn]; valIn = rowIn.getScaledSInt64FieldAsXFloat<long double>(colIn, scale);
if (valIn != 0 && scale > 0)
{
valIn /= pow(10.0, scale);
}
} }
else else
{ {
@ -3366,8 +3358,8 @@ void RowAggregationUM::calculateStatisticsFunctions()
long double sum1 = fRow.getLongDoubleField(colAux); long double sum1 = fRow.getLongDoubleField(colAux);
long double sum2 = fRow.getLongDoubleField(colAux + 1); long double sum2 = fRow.getLongDoubleField(colAux + 1);
int scale = fRow.getScale(colOut); uint32_t scale = fRow.getScale(colOut);
long double factor = pow(10.0, scale); auto factor = datatypes::scaleDivisor<long double>(scale);
if (scale != 0) // adjust the scale if necessary if (scale != 0) // adjust the scale if necessary
{ {
@ -3732,7 +3724,8 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData
else if (width <= datatypes::MAXLEGACYWIDTH) else if (width <= datatypes::MAXLEGACYWIDTH)
{ {
double dbl = strtod(aggData.fConstValue.c_str(), 0); double dbl = strtod(aggData.fConstValue.c_str(), 0);
double scale = pow(10.0, (double) fRowGroupOut->getScale()[i]); auto scale = datatypes::scaleDivisor<double>(fRowGroupOut->getScale()[i]);
// TODO: isn't overflow possible below:
fRow.setIntField((int64_t)(scale * dbl), colOut); fRow.setIntField((int64_t)(scale * dbl), colOut);
} }
else else
@ -3862,7 +3855,8 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData
else if (width == datatypes::MAXLEGACYWIDTH) else if (width == datatypes::MAXLEGACYWIDTH)
{ {
double dbl = strtod(aggData.fConstValue.c_str(), 0); double dbl = strtod(aggData.fConstValue.c_str(), 0);
dbl *= pow(10.0, (double) fRowGroupOut->getScale()[i]); // TODO: isn't precision loss possible below?
dbl *= datatypes::scaleDivisor<double>(fRowGroupOut->getScale()[i]);
dbl *= rowCnt; dbl *= rowCnt;
if ((dbl > 0 && dbl > (double) numeric_limits<int64_t>::max()) || if ((dbl > 0 && dbl > (double) numeric_limits<int64_t>::max()) ||
@ -4077,9 +4071,9 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData
case execplan::CalpontSystemCatalog::UDECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL:
{ {
double dbl = strtod(aggData.fConstValue.c_str(), 0); double dbl = strtod(aggData.fConstValue.c_str(), 0);
double scale = pow(10.0, (double) fRowGroupOut->getScale()[i]); // TODO: isn't overflow possible below?
datum.columnData = (int64_t)(scale * dbl); datum.columnData = (int64_t) (dbl * datatypes::scaleDivisor<double>(fRowGroupOut->getScale()[i]));
datum.scale = scale; datum.scale = fRowGroupOut->getScale()[i];
datum.precision = fRowGroupOut->getPrecision()[i]; datum.precision = fRowGroupOut->getPrecision()[i];
} }
break; break;
@ -4454,12 +4448,8 @@ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut,
} }
else if (width <= datatypes::MAXLEGACYWIDTH) else if (width <= datatypes::MAXLEGACYWIDTH)
{ {
valIn = rowIn.getIntField(colIn); uint32_t scale = fRowGroupIn.getScale()[colIn];
double scale = (double)(fRowGroupIn.getScale())[colIn]; valIn = rowIn.getScaledSInt64FieldAsXFloat<long double>(colIn, scale);
if (valIn != 0 && scale > 0)
{
valIn /= pow(10.0, scale);
}
} }
else else
{ {

View File

@ -376,6 +376,38 @@ public:
inline uint64_t getUintField(uint32_t colIndex) const; inline uint64_t getUintField(uint32_t colIndex) const;
template<int len> inline int64_t getIntField(uint32_t colIndex) const; template<int len> inline int64_t getIntField(uint32_t colIndex) const;
inline int64_t getIntField(uint32_t colIndex) const; inline int64_t getIntField(uint32_t colIndex) const;
// Get a signed 64-bit integer column value, convert to the given
// floating point data type T (e.g. float, double, long double)
// and divide it according to the scale.
template<typename T>
inline T getScaledSInt64FieldAsXFloat(uint32_t colIndex, uint32_t scale) const
{
const T d = getIntField(colIndex);
if (!scale)
return d;
return d / datatypes::scaleDivisor<T>(scale);
}
template<typename T>
inline T getScaledSInt64FieldAsXFloat(uint32_t colIndex) const
{
return getScaledSInt64FieldAsXFloat<T>(colIndex, getScale(colIndex));
}
// Get an unsigned 64-bit integer column value, convert to the given
// floating point data type T (e.g. float, double, long double)
// and divide it according to the scale.
template<typename T>
inline T getScaledUInt64FieldAsXFloat(uint32_t colIndex, uint32_t scale) const
{
const T d = getUintField(colIndex);
if (!scale)
return d;
return d / datatypes::scaleDivisor<T>(scale);
}
template<typename T>
inline T getScaledUInt64FieldAsXFloat(uint32_t colIndex) const
{
return getScaledUInt64FieldAsXFloat<T>(colIndex, getScale(colIndex));
}
template<typename T> template<typename T>
inline bool equals(T* value, uint32_t colIndex) const; inline bool equals(T* value, uint32_t colIndex) const;
template<int len> inline bool equals(uint64_t val, uint32_t colIndex) const; template<int len> inline bool equals(uint64_t val, uint32_t colIndex) const;

View File

@ -633,7 +633,7 @@ protected:
{ {
double val = convertAnyTo<double>(datum.columnData); double val = convertAnyTo<double>(datum.columnData);
if (val != 0 && datum.scale > 0) if (val != 0 && datum.scale > 0)
val /= pow(10.0, (double) datum.scale); val /= datatypes::scaleDivisor<double>(datum.scale);
return val; return val;
} }

View File

@ -181,16 +181,16 @@ double MCS_add::getDoubleVal(Row& row,
else if (op1.scale >= op2.scale) else if (op1.scale >= op2.scale)
{ {
dec.scale = op2.scale; dec.scale = op2.scale;
op1.value *= (int64_t)pow((double)10, op1.scale - op2.scale); op1.value *= datatypes::scaleDivisor<int64_t>((uint32_t) (op1.scale - op2.scale));
} }
else else
{ {
dec.scale = op1.scale; dec.scale = op1.scale;
op2.value *= (int64_t)pow((double)10, op2.scale - op1.scale); op2.value *= datatypes::scaleDivisor<int64_t>((uint32_t) (op2.scale - op1.scale));
} }
dec.value = op1.value + op2.value; dec.value = op1.value + op2.value;
return (double)(dec.value / pow((double)10, dec.scale)); return dec.decimal64ToXFloat<double>();
} }
default: default:

View File

@ -191,8 +191,8 @@ void WF_stats<T>::operator()(int64_t b, int64_t e, int64_t c)
if (fCount > 1) if (fCount > 1)
{ {
int scale = fRow.getScale(colIn); uint32_t scale = fRow.getScale(colIn);
long double factor = pow(10.0, scale); auto factor = datatypes::scaleDivisor<long double>(scale);
long double ldSum1 = fSum1; long double ldSum1 = fSum1;
long double ldSum2 = fSum2; long double ldSum2 = fSum2;