From 3ec432bd53198866b143e0d43ac3624b421d4977 Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Thu, 29 Feb 2024 12:31:07 -1000 Subject: [PATCH] dev: rename/improve amountSetFullPrecisionUpTo, add mixedAmountSetFullPrecisionUpTo --- hledger-lib/Hledger/Data/Amount.hs | 39 +++++++++++++++++--------- hledger-lib/Hledger/Data/Valuation.hs | 4 +-- hledger/Hledger/Cli/Commands/Prices.hs | 2 +- hledger/Hledger/Cli/Commands/Roi.hs | 2 +- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/hledger-lib/Hledger/Data/Amount.hs b/hledger-lib/Hledger/Data/Amount.hs index 2aec34e9d..844ad4431 100644 --- a/hledger-lib/Hledger/Data/Amount.hs +++ b/hledger-lib/Hledger/Data/Amount.hs @@ -97,7 +97,7 @@ module Hledger.Data.Amount ( amountSetPrecisionMax, withPrecision, amountSetFullPrecision, - amountSetFullPrecisionOr, + amountSetFullPrecisionUpTo, amountInternalPrecision, amountDisplayPrecision, defaultMaxPrecision, @@ -159,6 +159,7 @@ module Hledger.Data.Amount ( wbUnpack, mixedAmountSetPrecision, mixedAmountSetFullPrecision, + mixedAmountSetFullPrecisionUpTo, mixedAmountSetPrecisionMin, mixedAmountSetPrecisionMax, @@ -453,24 +454,26 @@ amountSetFullPrecision a = amountSetPrecision p a -- | We often want to display "infinite decimal" amounts rounded to some readable --- number of digits, while still displaying amounts with a large "non infinite" number --- of decimal digits (eg, 100 or 200 digits) in full. +-- number of digits, while still displaying amounts with a large but "non infinite" +-- number of decimal digits (eg 10 or 100 or 200 digits) in full. -- This helper is like amountSetFullPrecision, but with some refinements: --- 1. If the internal precision is the maximum (255), indicating an infinite decimal, --- the display precision is set to a smaller hard-coded default (8). --- 2. A maximum display precision can be specified, setting a hard upper limit. +-- +-- 1. A maximum display precision can be specified, setting a hard upper limit. +-- +-- 2. If no limit is specified, and the internal precision is the maximum (255), +-- indicating an infinite decimal, display precision is set to a smaller default (8). +-- -- This function always sets an explicit display precision (ie, Precision n). -amountSetFullPrecisionOr :: Maybe Word8 -> Amount -> Amount -amountSetFullPrecisionOr mmaxp a = amountSetPrecision (Precision p2) a +-- +amountSetFullPrecisionUpTo :: Maybe Word8 -> Amount -> Amount +amountSetFullPrecisionUpTo mmaxp a = amountSetPrecision (Precision p) a where - p1 = if -- dbg0 "maxdigits" $ - amountHasMaxDigits a then defaultMaxPrecision else max disp intp - -- & dbg0 "p1" + p = case mmaxp of + Just maxp -> min maxp $ max disp intp + Nothing -> if amountHasMaxDigits a then defaultMaxPrecision else max disp intp where - intp = amountInternalPrecision a disp = amountDisplayPrecision a - p2 = maybe p1 (min p1) mmaxp - -- & dbg0 "p2" + intp = amountInternalPrecision a -- | The fallback display precision used when showing amounts -- representing an infinite decimal. @@ -1228,6 +1231,14 @@ mixedAmountSetPrecision p = mapMixedAmountUnsafe (amountSetPrecision p) mixedAmountSetFullPrecision :: MixedAmount -> MixedAmount mixedAmountSetFullPrecision = mapMixedAmountUnsafe amountSetFullPrecision +-- | In each component amount, increase the display precision sufficiently +-- to render it exactly if possible, but not more than the given max precision, +-- and if no max precision is given and the amount has infinite decimals, +-- limit display precision to a hard-coded smaller number (8). +-- See amountSetFullPrecisionUpTo. +mixedAmountSetFullPrecisionUpTo :: Maybe Word8 -> MixedAmount -> MixedAmount +mixedAmountSetFullPrecisionUpTo mmaxp = mapMixedAmountUnsafe (amountSetFullPrecisionUpTo mmaxp) + -- | In each component amount, ensure the display precision is at least the given value. -- Makes all amounts have an explicit Precision. mixedAmountSetPrecisionMin :: Word8 -> MixedAmount -> MixedAmount diff --git a/hledger-lib/Hledger/Data/Valuation.hs b/hledger-lib/Hledger/Data/Valuation.hs index 7e174e347..614f59a4d 100644 --- a/hledger-lib/Hledger/Data/Valuation.hs +++ b/hledger-lib/Hledger/Data/Valuation.hs @@ -115,7 +115,7 @@ amountPriceDirectiveFromCost :: Day -> Amount -> Maybe PriceDirective amountPriceDirectiveFromCost d amt@Amount{acommodity=fromcomm, aquantity=n} = case acost amt of Just (UnitCost u) -> Just $ pd{pdamount=u} Just (TotalCost t) | n /= 0 -> Just $ pd{pdamount=u} - where u = amountSetFullPrecisionOr Nothing $ divideAmount n t + where u = amountSetFullPrecisionUpTo Nothing $ divideAmount n t _ -> Nothing where pd = PriceDirective{pddate = d, pdcommodity = fromcomm, pdamount = nullamt} @@ -209,7 +209,7 @@ amountValueAtDate priceoracle styles mto d a = -- set the display precision to match the internal precision (showing all digits), -- unnormalised (don't strip trailing zeros); -- but if it looks like an infinite decimal, limit the precision to 8. - & amountSetFullPrecisionOr Nothing + & amountSetFullPrecisionUpTo Nothing & dbg9With (lbl "calculated value".showAmount) -- | Calculate the gain of each component amount, that is the difference diff --git a/hledger/Hledger/Cli/Commands/Prices.hs b/hledger/Hledger/Cli/Commands/Prices.hs index 0d46899d9..65ac476f1 100644 --- a/hledger/Hledger/Cli/Commands/Prices.hs +++ b/hledger/Hledger/Cli/Commands/Prices.hs @@ -107,7 +107,7 @@ reversePriceDirective pd@PriceDirective{pdcommodity=c, pdamount=a} where lbl = lbl_ "reversePriceDirective" a' = - amountSetFullPrecisionOr (Just defaultMaxPrecision) $ + amountSetFullPrecisionUpTo (Just defaultMaxPrecision) $ invertAmount a{acommodity=c} & dbg9With (lbl "calculated reverse price".showAmount) -- & dbg9With (lbl "precision of reverse price".show.amountDisplayPrecision) diff --git a/hledger/Hledger/Cli/Commands/Roi.hs b/hledger/Hledger/Cli/Commands/Roi.hs index 0ec91c5a4..28c1bb9a3 100644 --- a/hledger/Hledger/Cli/Commands/Roi.hs +++ b/hledger/Hledger/Cli/Commands/Roi.hs @@ -147,7 +147,7 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{_rsReportOpts=ReportO , T.pack $ showMixedAmount $ styleAmounts styles $ cashFlowAmt -- , T.pack $ showMixedAmount $ -- -- dbg0With (lbl "cashflow after styling".showMixedAmountOneLine) $ - -- mapMixedAmount (amountSetFullPrecisionOr (Just defaultMaxPrecision)) $ + -- mapMixedAmount (amountSetFullPrecisionUpTo (Just defaultMaxPrecision)) $ -- styleAmounts (styles -- -- & dbg0With (lbl "styles".show)) -- cashFlowAmt