From a1c17112416949c0bd3af78f2edb45bfc7c6323d Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Wed, 12 Jun 2024 13:11:28 -0600 Subject: [PATCH 1/5] Use Int256 to avoid BigInt in FD operations. We do not here explicitly introduce support for FD{BitIntegers.Int256}, though that should work out of the box both before and after this PR. Rather, this PR _uses_ a (U)Int256 under the hood to prevent allocations from Int128 widening to BigInt in FD operations. --- Project.toml | 1 + src/FixedPointDecimals.jl | 32 +++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/Project.toml b/Project.toml index 3f313f9..2301391 100644 --- a/Project.toml +++ b/Project.toml @@ -4,6 +4,7 @@ authors = ["Fengyang Wang ", "Curtis Vogt Date: Wed, 12 Jun 2024 13:27:48 -0600 Subject: [PATCH 2/5] Further reduce BigInts by skipping a `rem()` in iseven --- src/FixedPointDecimals.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/FixedPointDecimals.jl b/src/FixedPointDecimals.jl index 317699b..ac9e5b5 100644 --- a/src/FixedPointDecimals.jl +++ b/src/FixedPointDecimals.jl @@ -175,7 +175,9 @@ function _round_to_nearest(quotient::T, divisor::T, ::RoundingMode{M}=RoundNearest) where {T <: Integer, M} halfdivisor = divisor >> 1 - if iseven(divisor) && remainder == halfdivisor + # PERF Note: Only need the last bit to check iseven, and default iseven(Int256) + # allocates, so we truncate first. + if iseven((divisor % Int8)) && remainder == halfdivisor # `:NearestTiesAway` will tie away from zero, e.g. -8.5 -> # -9. `:NearestTiesUp` will always ties towards positive # infinity. `:Nearest` will tie towards the nearest even From 78e45dc31960b960728dd6c1825132ee771e783f Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Wed, 12 Jun 2024 13:39:22 -0600 Subject: [PATCH 3/5] Fix ambiguity in _widemul(Int256, UInt256) --- src/FixedPointDecimals.jl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/FixedPointDecimals.jl b/src/FixedPointDecimals.jl index ac9e5b5..28b8611 100644 --- a/src/FixedPointDecimals.jl +++ b/src/FixedPointDecimals.jl @@ -123,17 +123,16 @@ end # Custom widemul implementation to avoid the cost of widening to BigInt. # FD{Int128} operations should widen to 256 bits internally, rather than to a BigInt. const BitInteger128 = Union{Int128, UInt128} -_widemul(x, y) = widemul(x, y) -_widemul(x::BitInteger128, y) = _widemul(promote(x, y)...) -_widemul(x, y::BitInteger128) = _widemul(promote(x, y)...) -_widemul(x::Int128, y::Int128) = BitIntegers.Int256(x) * BitIntegers.Int256(y) -_widemul(x::UInt128, y::UInt128) = BitIntegers.UInt256(x) * BitIntegers.UInt256(y) +_widemul(x, y) = _widen(x) * _widen(y) +_widemul(x::Signed,y::Unsigned) = _widen(x) * signed(_widen(y)) +_widemul(x::Unsigned,y::Signed) = signed(_widen(x)) * _widen(y) # Custom widen implementation to avoid the cost of widening to BigInt. # FD{Int128} operations should widen to 256 bits internally, rather than to a BigInt. _widen(::Type{Int128}) = BitIntegers.Int256 _widen(::Type{UInt128}) = BitIntegers.UInt256 -_widen(t) = widen(t) +_widen(t::Type) = widen(t) +_widen(x::T) where {T} = (_widen(T))(x) (::Type{T})(x::Real) where {T <: FD} = convert(T, x) From 879c60229e436dbf5d942a522571600b067d5708 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Wed, 12 Jun 2024 13:59:47 -0600 Subject: [PATCH 4/5] Bump patch version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 2301391..f3fcdaf 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "FixedPointDecimals" uuid = "fb4d412d-6eee-574d-9565-ede6634db7b0" authors = ["Fengyang Wang ", "Curtis Vogt "] -version = "0.5.2" +version = "0.5.3" [deps] BitIntegers = "c3b6d118-76ef-56ca-8cc7-ebb389d030a1" From a24565110dc16462cb2e7b2bd81adb161bd9ef20 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Wed, 12 Jun 2024 14:01:10 -0600 Subject: [PATCH 5/5] Add compat for BitIntegers --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index f3fcdaf..f120b6c 100644 --- a/Project.toml +++ b/Project.toml @@ -9,6 +9,7 @@ Parsers = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" [compat] Parsers = "2.7" +BitIntegers = "0.3.1" julia = "1.6" [extras]