test: Add isZeroAtScale coverage to STAmount_test

Tests the new STAmount::isZeroAtScale method across IOU, XRP, and MPT
amounts, covering the zero, sub-ULP, one-ULP, and scale-equals-exponent
short-circuit cases.
This commit is contained in:
Vito
2026-05-14 15:30:12 +02:00
parent 42eadf0416
commit 20678e6bc4

View File

@@ -1209,6 +1209,72 @@ public:
//--------------------------------------------------------------------------
void
testIsZeroAtScale()
{
testcase("isZeroAtScale");
Issue const usd{Currency(0x5553440000000000), AccountID(0x4985601)};
// IOU: 10 IOU — mantissa = kMIN_VALUE (10^15), exponent = -14.
// One ULP at this scale is 10^-14; half-ULP is 5*10^-15.
{
STAmount const ref{usd, STAmount::kMIN_VALUE, -14};
int const refScale = ref.exponent(); // -14
BEAST_EXPECT(refScale == -14);
// Zero rounds to zero at any scale.
STAmount const iouZero{usd, 0};
BEAST_EXPECT(iouZero.isZeroAtScale(refScale));
// Sub-ULP: 1e-16 IOU (mantissa = kMIN_VALUE, exponent = -31).
// Far below half-ULP → rounds to zero.
STAmount const subUlp{usd, STAmount::kMIN_VALUE, -31};
BEAST_EXPECT(subUlp.isZeroAtScale(refScale));
// One ULP: 1e-14 IOU (mantissa = kMIN_VALUE, exponent = -29).
// Exactly the smallest representable unit at refScale → not zero.
STAmount const oneUlp{usd, STAmount::kMIN_VALUE, -29};
BEAST_EXPECT(!oneUlp.isZeroAtScale(refScale));
// The reference value itself: exponent == scale → returned
// unchanged → not zero.
BEAST_EXPECT(!ref.isZeroAtScale(refScale));
// A much larger value: certainly not zero at this scale.
STAmount const large{usd, STAmount::kMIN_VALUE, 0}; // 1e15 IOU
BEAST_EXPECT(!large.isZeroAtScale(refScale));
// When scale equals the value's own exponent, roundToScale
// short-circuits and returns the value unchanged.
BEAST_EXPECT(!subUlp.isZeroAtScale(subUlp.exponent()));
BEAST_EXPECT(!oneUlp.isZeroAtScale(oneUlp.exponent()));
}
// XRP is integral — roundToScale short-circuits, value is preserved.
{
STAmount const xrp{XRPAmount{1}};
BEAST_EXPECT(!xrp.isZeroAtScale(-14));
BEAST_EXPECT(!xrp.isZeroAtScale(0));
STAmount const xrpZero{XRPAmount{0}};
BEAST_EXPECT(xrpZero.isZeroAtScale(-14));
}
// MPT is integral — same short-circuit behaviour as XRP.
{
MPTIssue const mpt{makeMptID(1, AccountID(0x4985601))};
STAmount const mptAmt{mpt, 1};
BEAST_EXPECT(!mptAmt.isZeroAtScale(0));
BEAST_EXPECT(!mptAmt.isZeroAtScale(-14));
STAmount const mptZero{mpt, 0};
BEAST_EXPECT(mptZero.isZeroAtScale(0));
}
}
//--------------------------------------------------------------------------
void
run() override
{
@@ -1227,6 +1293,7 @@ public:
testCanSubtractXRP();
testCanSubtractIOU();
testCanSubtractMPT();
testIsZeroAtScale();
}
};