Skip to content

Commit 21b41a2

Browse files
committed
Fixup BigInt/BigFloat conversions: Restore old implementation, but specialize f=1 case
Before: ``` julia> @Btime convert(FixedDecimal{BigInt,1}, $(BigInt(1))) 113.644 ns (7 allocations: 128 bytes) FixedDecimal{BigInt,1}(1.0) julia> @Btime convert(FixedDecimal{BigInt,1}, $(1)) 152.583 ns (9 allocations: 168 bytes) FixedDecimal{BigInt,1}(1.0) julia> @Btime convert(FixedDecimal{BigInt,2}, $(BigInt(1))) 132.985 ns (8 allocations: 136 bytes) FixedDecimal{BigInt,2}(1.00) julia> @Btime convert(FixedDecimal{BigInt,2}, $(1)) 175.048 ns (10 allocations: 176 bytes) FixedDecimal{BigInt,2}(1.00) ``` After: ``` julia> @Btime convert(FixedDecimal{BigInt,1}, $(BigInt(1))) 2.000 ns (0 allocations: 0 bytes) FixedDecimal{BigInt,1}(0.1) julia> @Btime convert(FixedDecimal{BigInt,1}, $(1)) 28.684 ns (2 allocations: 40 bytes) FixedDecimal{BigInt,1}(0.1) julia> @Btime convert(FixedDecimal{BigInt,2}, $(BigInt(1))) 132.382 ns (8 allocations: 136 bytes) FixedDecimal{BigInt,2}(1.00) julia> @Btime convert(FixedDecimal{BigInt,2}, $(1)) 131.776 ns (8 allocations: 136 bytes) FixedDecimal{BigInt,2}(1.00) ```
1 parent df44234 commit 21b41a2

File tree

2 files changed

+18
-0
lines changed

2 files changed

+18
-0
lines changed

src/FixedPointDecimals.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,18 @@ function Base.convert(::Type{FD{T, f}}, x::Integer) where {T, f}
308308
end
309309
reinterpret(FD{T, f}, v)
310310
end
311+
function Base.convert(::Type{FD{BigT, f}}, x::Integer) where {BigT<:Union{BigFloat,BigInt}, f}
312+
# We specialize on f==1, since julia can't eliminate BigInt multiplication.
313+
if f == 1
314+
# If x is already a BigInt, this is a no-op, otherwise we alloc a new BigInt.
315+
return reinterpret(FD{BigT, f}, BigT(x))
316+
end
317+
# For the normal case, we multiply by C, which produces a BigInt value.
318+
C = coefficient(FD{BigT, f})
319+
# This can't throw since BigInt and BigFloat can hold any number.
320+
v = x * C
321+
reinterpret(FD{BigT, f}, v)
322+
end
311323

312324
Base.convert(::Type{T}, x::AbstractFloat) where {T <: FD} = round(T, x)
313325

test/FixedDecimal.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,12 @@ const UWFD2 = FixedDecimal{UInt128, 2}
360360
@test @allocated(Base.convert(FD2, Int128(-1))) == 0
361361
end
362362

363+
@testset "BigInt conversion performance" begin
364+
b = BigInt(2)
365+
# Special-cased f=1 to not allocate for BigInt => FD conversion
366+
@test @allocated(Base.convert(FixedDecimal{BigInt, 1}, b)) == 0
367+
end
368+
363369
end # module PerfTests
364370

365371
@testset "promotion" begin

0 commit comments

Comments
 (0)