Skip to content

Commit ea46f72

Browse files
committed
Add checked / operation for FDs: checked_decimal_division
1 parent f19c147 commit ea46f72

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

src/FixedPointDecimals.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,30 @@ function Base.checked_div(x::FD{T,f}, y::FD{T,f}) where {T<:Integer,f}
421421
return reinterpret(FD{T, f}, v)
422422
end
423423

424+
# We introduce a new function for this since Base.Checked only supports integers, and ints
425+
# don't have a decimal division operation.
426+
"""
427+
FixedPointDecimals.checked_decimal_division(x::FD, y::FD) -> FD
428+
429+
Calculates `x / y`, checking for overflow errors where applicable.
430+
431+
The overflow protection may impose a perceptible performance penalty.
432+
433+
See also:
434+
- `Base.checked_div` for truncating division.
435+
"""
436+
checked_decimal_division(x::FD, y::FD) = checked_decimal_division(promote(x, y)...)
437+
checked_decimal_division(x, y::FD) = checked_decimal_division(promote(x, y)...)
438+
checked_decimal_division(x::FD, y) = checked_decimal_division(promote(x, y)...)
439+
440+
function checked_decimal_division(x::FD{T,f}, y::FD{T,f}) where {T<:Integer,f}
441+
powt = coefficient(FD{T, f})
442+
quotient, remainder = fldmod(widemul(x.i, powt), y.i)
443+
v = _round_to_nearest(quotient, remainder, y.i)
444+
typemin(T) <= v <= typemax(T) || Base.Checked.throw_overflowerr_binaryop(:/, x, y)
445+
return reinterpret(FD{T, f}, v)
446+
end
447+
424448
# --------------------------
425449

426450
Base.convert(::Type{AbstractFloat}, x::FD) = convert(floattype(typeof(x)), x)

test/FixedDecimal.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,13 @@ end
630630

631631
@test_throws OverflowError Base.checked_div(Int8(1), FD{Int8,2}(0.5))
632632
@test_throws OverflowError Base.checked_div(FD{Int8,2}(1), FD{Int8,2}(0.4))
633+
634+
@testset "checked_decimal_division" begin
635+
using FixedPointDecimals: checked_decimal_division
636+
637+
@test checked_decimal_division(Int8(1), FD{Int8,2}(0.8)) == FD{Int8,2}(1.25)
638+
@test_throws OverflowError checked_decimal_division(Int8(1), FD{Int8,2}(0.7))
639+
end
633640
end
634641

635642
@testset "limits of $T" for T in CONTAINER_TYPES

0 commit comments

Comments
 (0)