Skip to content

Commit 9c1688d

Browse files
committed
FixedDec <=> FixedDec conversion performance
1 parent 7d75aa1 commit 9c1688d

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

src/FixedPointDecimals.jl

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -302,10 +302,7 @@ function Base.convert(::Type{FD{T, f}}, x::Integer) where {T, f}
302302
xT = convert(T, x) # This won't throw, since we already checked, above.
303303
# Perform x * C, and check for overflow. This is cheaper than a widemul, especially for
304304
# 128-bit T, since those widen into a BigInt.
305-
v, overflow = Base.mul_with_overflow(xT, C)
306-
if overflow
307-
throw_inexact()
308-
end
305+
v = _mul_checked_overflow(throw_inexact, xT, C)
309306
reinterpret(FD{T, f}, v)
310307
end
311308
function Base.convert(::Type{FD{BigInt, f}}, x::Integer) where {f}
@@ -321,6 +318,15 @@ function Base.convert(::Type{FD{BigInt, f}}, x::Integer) where {f}
321318
reinterpret(FD{BigInt, f}, v)
322319
end
323320

321+
# x * y - if overflow, report an InexactError(FDT, )
322+
function _mul_checked_overflow(overflow_callback, x, y)
323+
v, overflow = Base.mul_with_overflow(x, y)
324+
if overflow
325+
overflow_callback()
326+
end
327+
return v
328+
end
329+
324330
Base.convert(::Type{T}, x::AbstractFloat) where {T <: FD} = round(T, x)
325331

326332
function Base.convert(::Type{FD{T, f}}, x::Rational) where {T, f}
@@ -332,7 +338,10 @@ function Base.convert(::Type{FD{T, f}}, x::FD{U, g}) where {T, f, U, g}
332338
if f g
333339
# Compute `10^(f - g)` without overflow
334340
powt = div(coefficient(FD{T, f}), coefficient(FD{U, g}))
335-
reinterpret(FD{T, f}, T(widemul(x.i, powt)))
341+
v = _mul_checked_overflow(promote(x.i, powt)...) do
342+
throw(InexactError(:convert, FD{T, f}, x))
343+
end
344+
reinterpret(FD{T, f}, T(v))
336345
else
337346
# Compute `10^(g - f)` without overflow
338347
powt = div(coefficient(FD{U, g}), coefficient(FD{T, f}))

test/FixedDecimal.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ const SFD4 = FixedDecimal{Int16, 4}
336336
const F64D2 = FixedDecimal{Int64, 2}
337337
const UF64D2 = FixedDecimal{UInt64, 2}
338338
const WFD2 = FixedDecimal{Int128, 2}
339+
const WFD3 = FixedDecimal{Int128, 3}
339340
const UFD2 = FixedDecimal{UInt, 2}
340341
const UWFD2 = FixedDecimal{UInt128, 2}
341342

@@ -369,6 +370,19 @@ const UWFD2 = FixedDecimal{UInt128, 2}
369370
@test @allocated(convert(UF64D2, UInt128(1))) == 0
370371
@test @allocated(convert(F64D2, Int128(-1))) == 0
371372
end
373+
374+
@testset "128-bit FD to FD conversion performance" begin
375+
@test @allocated(convert(WFD3, WFD2(1))) == 0
376+
@test @allocated(convert(SFD4, SFD2(1))) == 0
377+
@test @allocated(convert(SFD4, WFD2(1))) == 0
378+
end
379+
380+
@testset "128-bit FD to FD conversion performance" begin
381+
@test @allocated(convert(WFD3, WFD2(1))) == 0
382+
@test @allocated(convert(SFD4, SFD2(1))) == 0
383+
@test @allocated(convert(SFD4, WFD2(1))) == 0
384+
end
385+
372386
end # if @static Int === Int64
373387

374388
@testset "BigInt conversion performance" begin

0 commit comments

Comments
 (0)