Skip to content

Commit cdd6966

Browse files
mbarbarNHDaly
andauthored
Add div_with_overflow (#106)
* Remove promoting with_overflow functions. * Bump Project.toml: 0.5.6 --------- Co-authored-by: Nathan Daly <NHDaly@gmail.com>
1 parent 20c21c5 commit cdd6966

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "FixedPointDecimals"
22
uuid = "fb4d412d-6eee-574d-9565-ede6634db7b0"
33
authors = ["Fengyang Wang <fengyang.wang.0@gmail.com>", "Curtis Vogt <curtis.vogt@gmail.com>"]
4-
version = "0.5.5"
4+
version = "0.5.6"
55

66
[deps]
77
BitIntegers = "c3b6d118-76ef-56ca-8cc7-ebb389d030a1"

src/FixedPointDecimals.jl

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export FixedDecimal, RoundThrows
3232

3333
# (Re)export checked_* arithmetic functions
3434
# - Defined in this package:
35-
export checked_rdiv
35+
export checked_rdiv, div_with_overflow
3636
# - Reexported from Base:
3737
export checked_abs, checked_add, checked_cld, checked_div, checked_fld,
3838
checked_mod, checked_mul, checked_neg, checked_rem, checked_sub
@@ -441,6 +441,27 @@ Base.Checked.mul_with_overflow(x::FD, y::FD) = Base.Checked.mul_with_overflow(pr
441441
Base.Checked.mul_with_overflow(x::FD, y) = Base.Checked.mul_with_overflow(promote(x, y)...)
442442
Base.Checked.mul_with_overflow(x, y::FD) = Base.Checked.mul_with_overflow(promote(x, y)...)
443443

444+
# This does not exist in Base so is just part of this package.
445+
# Throws on divide by zero.
446+
@doc """
447+
div_with_overflow(x::FixedDecimal{T,f}, y::FixedDecimal{T,f})::(FixedDecimal{T,f}, Bool)
448+
where {T<:Integer, f}
449+
450+
Return the result of div (wrapping on overflow/underflow) and a boolean indicating whether
451+
overflow/underflow did in fact happen. Throws a DivideError on divide-by-zero.
452+
"""
453+
function div_with_overflow(x::FD{T,f}, y::FD{T,f}) where {T<:Integer,f}
454+
C = coefficient(FD{T, f})
455+
# This case will break the div call below.
456+
if x.i == typemin(T) && y.i == -1
457+
# To perform the div and overflow means reaching the max and adding 1, so typemin.
458+
return (x, true)
459+
end
460+
# Note: The div() will throw for divide-by-zero, that's not an overflow.
461+
v, b = Base.Checked.mul_with_overflow(C, div(x.i, y.i))
462+
return (reinterpret(FD{T,f}, v), b)
463+
end
464+
444465
Base.checked_add(x::FD, y::FD) = Base.checked_add(promote(x, y)...)
445466
Base.checked_sub(x::FD, y::FD) = Base.checked_sub(promote(x, y)...)
446467
Base.checked_mul(x::FD, y::FD) = Base.checked_mul(promote(x, y)...)

test/FixedDecimal.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,10 @@ end
791791
@test Base.Checked.mul_with_overflow(FD{Int8,0}(120), 2) == (FD{Int8,0}(-16), true)
792792
@test Base.Checked.mul_with_overflow(120, FD{Int8,0}(2)) == (FD{Int8,0}(-16), true)
793793

794+
@test div_with_overflow(FD{Int8,2}(1), FD{Int8,2}(0.5)) == (FD{Int8,2}(-0.56), true)
795+
@test div_with_overflow(typemin(FD{Int32,0}), FD{Int32,0}(-1)) == (typemin(FD{Int32,0}), true)
796+
@test div_with_overflow(FD{Int16,1}(1639), FD{Int16,1}(0.5)) == (FD{Int16,1}(-3275.6), true)
797+
794798
@testset "with_overflow math corner cases" begin
795799
@testset for I in (Int128, UInt128, Int8, UInt8), f in (0,2)
796800
T = FD{I, f}
@@ -816,6 +820,16 @@ end
816820
issigned(I) && @test Base.Checked.mul_with_overflow(typemin(T), 2) == (typemin(T) * 2, true)
817821
issigned(I) && @test Base.Checked.mul_with_overflow(2, typemin(T)) == (2 * typemin(T), true)
818822
end
823+
824+
if f > 0
825+
@test div_with_overflow(typemax(T), eps(T))[2]
826+
issigned(I) && @test div_with_overflow(typemin(T), eps(T))[2]
827+
issigned(I) && @test div_with_overflow(typemax(T), -eps(T))[2]
828+
829+
issigned(I) && @test_throws DivideError div_with_overflow(typemax(T), T(0))
830+
issigned(I) && @test_throws DivideError div_with_overflow(typemin(T), T(0))
831+
issigned(I) && @test div_with_overflow(typemin(T), -eps(T))[2]
832+
end
819833
end
820834
end
821835

@@ -849,6 +863,12 @@ end
849863
@test Base.Checked.mul_with_overflow(FD{Int64,6}(2.22), 4) == (FD{Int64,6}(8.88), false)
850864
@test Base.Checked.mul_with_overflow(FD{Int128,14}(10), FD{Int128,14}(20.1)) == (FD{Int128,14}(201), false)
851865
@test Base.Checked.mul_with_overflow(FD{Int128,30}(10.11), FD{Int128,0}(1)) == (FD{Int128,30}(10.11), false)
866+
867+
@test div_with_overflow(FD{Int64,6}(4), FD{Int64,6}(2)) == (FD{Int64,6}(2), false)
868+
@test div_with_overflow(FD{Int32,6}(4), FD{Int32,6}(2.1)) == (FD{Int32,6}(1), false)
869+
@test div_with_overflow(FD{Int128,14}(10), FD{Int128,14}(20.1)) == (FD{Int128,14}(0), false)
870+
@test div_with_overflow(FD{Int128,30}(10.1), FD{Int128,30}(1)) == (FD{Int128,30}(10), false)
871+
@test div_with_overflow(typemin(FD{Int32,8}(1)), FD{Int32,8}(-1)) == (21, false)
852872
end
853873
end
854874

0 commit comments

Comments
 (0)