@@ -416,11 +416,14 @@ class Addition {
416
416
uint8_t aPrecision,
417
417
uint8_t aScale,
418
418
uint8_t bPrecision,
419
- uint8_t bScale) {
419
+ uint8_t bScale,
420
+ bool allowPrecisionLoss) {
420
421
auto precision = std::max (aPrecision - aScale, bPrecision - bScale) +
421
422
std::max (aScale, bScale) + 1 ;
422
423
auto scale = std::max (aScale, bScale);
423
- return DecimalUtil::adjustPrecisionScale (precision, scale);
424
+ return allowPrecisionLoss
425
+ ? DecimalUtil::adjustPrecisionScale (precision, scale)
426
+ : DecimalUtil::bounded (precision, scale);
424
427
}
425
428
};
426
429
@@ -464,9 +467,10 @@ class Subtraction {
464
467
uint8_t aPrecision,
465
468
uint8_t aScale,
466
469
uint8_t bPrecision,
467
- uint8_t bScale) {
470
+ uint8_t bScale,
471
+ bool allowPrecisionLoss) {
468
472
return Addition::computeResultPrecisionScale (
469
- aPrecision, aScale, bPrecision, bScale);
473
+ aPrecision, aScale, bPrecision, bScale, allowPrecisionLoss );
470
474
}
471
475
};
472
476
@@ -566,9 +570,12 @@ class Multiply {
566
570
uint8_t aPrecision,
567
571
uint8_t aScale,
568
572
uint8_t bPrecision,
569
- uint8_t bScale) {
570
- return DecimalUtil::adjustPrecisionScale (
571
- aPrecision + bPrecision + 1 , aScale + bScale);
573
+ uint8_t bScale,
574
+ const bool allowPrecisionLoss) {
575
+ return allowPrecisionLoss
576
+ ? DecimalUtil::adjustPrecisionScale (
577
+ aPrecision + bPrecision + 1 , aScale + bScale)
578
+ : DecimalUtil::bounded (aPrecision + bPrecision + 1 , aScale + bScale);
572
579
}
573
580
574
581
private:
@@ -616,10 +623,22 @@ class Divide {
616
623
uint8_t aPrecision,
617
624
uint8_t aScale,
618
625
uint8_t bPrecision,
619
- uint8_t bScale) {
620
- auto scale = std::max (6 , aScale + bPrecision + 1 );
621
- auto precision = aPrecision - aScale + bScale + scale;
622
- return DecimalUtil::adjustPrecisionScale (precision, scale);
626
+ uint8_t bScale,
627
+ bool allowPrecisionLoss) {
628
+ if (allowPrecisionLoss) {
629
+ auto scale = std::max (6 , aScale + bPrecision + 1 );
630
+ auto precision = aPrecision - aScale + bScale + scale;
631
+ return DecimalUtil::adjustPrecisionScale (precision, scale);
632
+ } else {
633
+ auto intDig = std::min (38 , aPrecision - aScale + bScale);
634
+ auto decDig = std::min (38 , std::max (6 , aScale + bPrecision + 1 ));
635
+ auto diff = (intDig + decDig) - 38 ;
636
+ if (diff > 0 ) {
637
+ decDig -= diff / 2 + 1 ;
638
+ intDig = 38 - decDig;
639
+ }
640
+ return DecimalUtil::bounded (intDig + decDig, decDig);
641
+ }
623
642
}
624
643
};
625
644
@@ -689,13 +708,14 @@ template <typename Operation>
689
708
std::shared_ptr<exec::VectorFunction> createDecimalFunction (
690
709
const std::string& name,
691
710
const std::vector<exec::VectorFunctionArg>& inputArgs,
692
- const core::QueryConfig& /* config*/ ) {
711
+ const core::QueryConfig& config) {
693
712
const auto & aType = inputArgs[0 ].type ;
694
713
const auto & bType = inputArgs[1 ].type ;
695
714
const auto [aPrecision, aScale] = getDecimalPrecisionScale (*aType);
696
715
const auto [bPrecision, bScale] = getDecimalPrecisionScale (*bType);
716
+ const bool allowPrecisionLoss = config.isAllowPrecisionLoss ();
697
717
const auto [rPrecision, rScale] = Operation::computeResultPrecisionScale (
698
- aPrecision, aScale, bPrecision, bScale);
718
+ aPrecision, aScale, bPrecision, bScale, allowPrecisionLoss );
699
719
const uint8_t aRescale =
700
720
Operation::computeRescaleFactor (aScale, bScale, rScale);
701
721
const uint8_t bRescale =
0 commit comments