Skip to content

Commit

Permalink
[MonetaryAmount] - Fix divide when result has no decimal part and res…
Browse files Browse the repository at this point in the history
…ult in adding 0
  • Loading branch information
sjanel committed Mar 29, 2024
1 parent c30d045 commit 9179133
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 15 deletions.
30 changes: 17 additions & 13 deletions src/objects/src/monetaryamount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,17 +451,17 @@ MonetaryAmount MonetaryAmount::operator/(MonetaryAmount div) const {
// Indeed, on 64 bits the unsigned integral type can hold one more digit than its signed counterpart.
static_assert(std::numeric_limits<UnsignedAmountType>::digits10 > std::numeric_limits<AmountType>::digits10);

int8_t lhsNbDigits = static_cast<int8_t>(ndigits(_amount));
int8_t lhsNbDigits = static_cast<int8_t>(ndigits(lhsAmount));
const int8_t lhsNbDigitsToAdd = std::numeric_limits<UnsignedAmountType>::digits10 - lhsNbDigits;
UnsignedAmountType lhs =
static_cast<UnsignedAmountType>(std::abs(lhsAmount)) * ipow10(static_cast<uint8_t>(lhsNbDigitsToAdd));
UnsignedAmountType rhs = static_cast<UnsignedAmountType>(std::abs(rhsAmount));
auto lhs = static_cast<UnsignedAmountType>(std::abs(lhsAmount)) * ipow10(static_cast<uint8_t>(lhsNbDigitsToAdd));
auto rhs = static_cast<UnsignedAmountType>(std::abs(rhsAmount));

int8_t lhsNbDecimals = nbDecimals() + lhsNbDigitsToAdd;

UnsignedAmountType totalIntPart = 0;
int8_t nbDecs = lhsNbDecimals - div.nbDecimals();
int8_t totalPartNbDigits;

while (true) {
totalIntPart += lhs / rhs; // Add integral part
totalPartNbDigits = static_cast<int8_t>(ndigits(totalIntPart));
Expand All @@ -481,16 +481,20 @@ MonetaryAmount MonetaryAmount::operator/(MonetaryAmount div) const {
}

if (nbDecs < 0) {
throw exception("Overflow during divide");
}

const int8_t nbDigitsTruncate = totalPartNbDigits - std::numeric_limits<AmountType>::digits10;
if (nbDigitsTruncate > 0) {
if (nbDecs < nbDigitsTruncate) {
throw exception("Overflow during divide");
if (std::numeric_limits<AmountType>::digits10 < totalPartNbDigits - nbDecs) {
throw exception("Overflow during divide {} / {}", *this, div);
}
totalIntPart *= ipow10(-nbDecs);
nbDecs = 0;
} else {
const int8_t nbDigitsTruncate = totalPartNbDigits - std::numeric_limits<AmountType>::digits10;
if (nbDigitsTruncate > 0) {
if (nbDecs < nbDigitsTruncate) {
throw exception("Overflow during divide {} / {}", *this, div);
}
totalIntPart /= ipow10(static_cast<uint8_t>(nbDigitsTruncate));
nbDecs -= nbDigitsTruncate;
}
totalIntPart /= ipow10(static_cast<uint8_t>(nbDigitsTruncate));
nbDecs -= nbDigitsTruncate;
}

return {static_cast<AmountType>(totalIntPart) * negMult, resCurrency, nbDecs};
Expand Down
6 changes: 4 additions & 2 deletions src/objects/test/monetaryamount_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,7 @@ TEST(MonetaryAmountTest, Divide) {
EXPECT_EQ(MonetaryAmount("-870.5647", CurrencyCode("ETH")) / MonetaryAmount("4709.3467736", CurrencyCode("ETH")),
MonetaryAmount("-0.18485890758358997"));
EXPECT_EQ(MonetaryAmount("487.76 EUR") / MonetaryAmount("1300.5 EUR"), MonetaryAmount("0.3750557477893118"));
MonetaryAmount res;
EXPECT_THROW(res = MonetaryAmount("100") / MonetaryAmount("0.00000000000000001"), exception);
EXPECT_THROW(MonetaryAmount(100) / MonetaryAmount("0.00000000000000001"), exception);
EXPECT_EQ(MonetaryAmount(10) / MonetaryAmount("0.0000000000000001"), MonetaryAmount("100000000000000000"));
EXPECT_EQ(MonetaryAmount("1000000000 KRW") / MonetaryAmount("922337203685477580 KRW"),
MonetaryAmount("0.00000000108420217"));
Expand All @@ -248,6 +247,9 @@ TEST(MonetaryAmountTest, OverflowProtectionDivide) {
MonetaryAmount("0.00000030482381689"));
EXPECT_EQ(MonetaryAmount("0.00000598978800261", "Magic4Life") / 17,
MonetaryAmount("0.00000035234047074", "Magic4Life"));

EXPECT_EQ(MonetaryAmount("1489950.87030903569", "KRW") / MonetaryAmount("0.29106287757551"),
MonetaryAmount(5119000, "KRW"));
}

TEST(MonetaryAmountTest, Convert) {
Expand Down

0 comments on commit 9179133

Please sign in to comment.