lib: More efficiently check whether Amounts are or look zero.

Comparing two Quantity (either with (==) or compare) does a lot of
normalisation (calling roundMax) which is unnecessary if we're comparing
to zero. Do things more directly to save work.

For reg -f examples/10000x10000x10.journal, this results in
- A 12% reduction in heap allocations, from 70GB to 62GB
- A 14% reduction in (profiled) time, from 79s to 70s
Results for bal -f examples/10000x10000x10.journal are of the same order
of magnitude.
This commit is contained in:
Stephen Morgan 2021-03-03 15:57:22 +11:00 committed by Simon Michael
parent 522c8a6ad3
commit 7fe58f1346

View File

@ -323,11 +323,15 @@ testAmountAndTotalPrice f amt = case aprice amt of
-- | Do this Amount and (and its total price, if it has one) appear to be zero when rendered with its
-- display precision ?
amountLooksZero :: Amount -> Bool
amountLooksZero = testAmountAndTotalPrice ((0==) . amountRoundedQuantity)
amountLooksZero = testAmountAndTotalPrice looksZero
where
looksZero Amount{aquantity=Decimal e q, astyle=AmountStyle{asprecision=p}} = case p of
Precision d -> if e > d then abs q <= 5*10^(e-d-1) else q == 0
NaturalPrecision -> q == 0
-- | Is this Amount (and its total price, if it has one) exactly zero, ignoring its display precision ?
amountIsZero :: Amount -> Bool
amountIsZero = testAmountAndTotalPrice ((0==) . aquantity)
amountIsZero = testAmountAndTotalPrice (\Amount{aquantity=Decimal _ q} -> q == 0)
-- | Set an amount's display precision, flipped.
withPrecision :: Amount -> AmountPrecision -> Amount