11using Base: BitInteger, promote, afoldl, @_inline_meta
2- import Base. Checked: checked_neg, checked_add, checked_sub, checked_mul, checked_abs
2+ import Base. Checked: checked_neg, checked_add, checked_sub, checked_mul, checked_abs,
3+ checked_div, checked_fld, checked_cld, checked_mod, checked_rem
34using Base. Checked: mul_with_overflow
45
56if VERSION ≥ v " 1.11-alpha"
1011 using Base. Checked: throw_overflowerr_binaryop
1112end
1213
14+ const SignedBitInteger = Union{Int8, Int16, Int32, Int64, Int128}
15+ const UnsignedBitInteger = Union{UInt8, UInt16, UInt32, UInt64, UInt128}
16+
1317# The Base methods have unchecked semantics, so just pass through
1418unchecked_neg (x... ) = Base.:- (x... )
1519unchecked_add (x... ) = Base.:+ (x... )
@@ -18,6 +22,13 @@ unchecked_mul(x...) = Base.:*(x...)
1822unchecked_pow (x... ) = Base.:^ (x... )
1923unchecked_abs (x... ) = Base. abs (x... )
2024
25+ # The Base div methods have checked semantics, so just pass through
26+ checked_div (x... ) = Base.:÷ (x... )
27+ checked_fld (x... ) = Base. fld (x... )
28+ checked_cld (x... ) = Base. cld (x... )
29+ checked_rem (x... ) = Base.:% (x... ) # Yes, % is `rem`, not `mod`
30+ checked_mod (x... ) = Base. mod (x... )
31+ checked_divrem (x... ) = Base. divrem (x... )
2132
2233# convert multi-argument calls into nested two-argument calls
2334checked_add (a, b, c, xs... ) = @checked (@_inline_meta ; afoldl (+ , (+ )((+ )(a, b), c), xs... ))
@@ -40,6 +51,13 @@ saturating_sub(x::Number, y::Number) = saturating_sub(promote(x, y)...)
4051saturating_mul (x:: Number , y:: Number ) = saturating_mul (promote (x, y)... )
4152saturating_pow (x:: Number , y:: Number ) = saturating_pow (promote (x, y)... )
4253
54+ saturating_div (x:: Number , y:: Number ) = saturating_div (promote (x, y)... )
55+ saturating_fld (x:: Number , y:: Number ) = saturating_fld (promote (x, y)... )
56+ saturating_cld (x:: Number , y:: Number ) = saturating_cld (promote (x, y)... )
57+ saturating_rem (x:: Number , y:: Number ) = saturating_rem (promote (x, y)... )
58+ saturating_mod (x:: Number , y:: Number ) = saturating_mod (promote (x, y)... )
59+ saturating_divrem (x:: Number , y:: Number ) = saturating_divrem (promote (x, y)... )
60+
4361
4462# fallback to `unchecked_` for `Number` types that don't have more specific `checked_` methods
4563checked_neg (x:: T ) where T <: Number = unchecked_neg (x)
@@ -56,6 +74,13 @@ saturating_mul(x::T, y::T) where T <: Number = unchecked_mul(x, y)
5674saturating_pow (x:: T , y:: T ) where T <: Number = unchecked_pow (x, y)
5775saturating_abs (x:: T ) where T <: Number = unchecked_abs (x)
5876
77+ saturating_div (x:: T , y:: T ) where T <: Number = saturating_div (x, y)
78+ saturating_fld (x:: T , y:: T ) where T <: Number = saturating_fld (x, y)
79+ saturating_cld (x:: T , y:: T ) where T <: Number = saturating_cld (x, y)
80+ saturating_rem (x:: T , y:: T ) where T <: Number = saturating_rem (x, y)
81+ saturating_mod (x:: T , y:: T ) where T <: Number = saturating_mod (x, y)
82+ saturating_divrem (x:: T , y:: T ) where T <: Number = saturating_divrem (x, y)
83+
5984
6085# fallback to `unchecked_` for non-`Number` types
6186checked_neg (x) = unchecked_neg (x)
@@ -66,6 +91,66 @@ checked_pow(x, y) = unchecked_pow(x, y)
6691checked_abs (x) = unchecked_abs (x)
6792
6893
94+ # fallback to `checked_` div methods for non-`Number` types
95+ unchecked_div (x, y) = checked_div (x, y)
96+ unchecked_fld (x, y) = checked_fld (x, y)
97+ unchecked_cld (x, y) = checked_cld (x, y)
98+ unchecked_rem (x, y) = checked_rem (x, y)
99+ unchecked_mod (x, y) = checked_mod (x, y)
100+ unchecked_divrem (x, y) = checked_divrem (x, y)
101+
102+
103+ # unchecked div implementations
104+ # integer division is so slow that these branches don't seem to matter?
105+ # We're making integer division unchecked by letting `÷ -1` just be negated unchecked,
106+ # and `÷ 0` be 0.
107+ unchecked_div (x:: T , y:: T ) where T <: SignedBitInteger =
108+ (y == zero (T)) ?
109+ zero (T) :
110+ (y == - one (T)) ?
111+ - x :
112+ Base. sdiv_int (x, y)
113+ unchecked_div (x:: T , y:: T ) where T <: UnsignedBitInteger =
114+ (y == zero (T)) ?
115+ zero (T) :
116+ Base. udiv_int (x, y)
117+
118+ function unchecked_fld (x:: T , y:: T ) where T <: SignedBitInteger
119+ d = unchecked_div (x, y)
120+ return y == 0 ?
121+ d :
122+ d - (signbit (x ⊻ y) & (d * y != x))
123+ end
124+ unchecked_fld (x:: T , y:: T ) where T <: UnsignedBitInteger = unchecked_div (x, y)
125+
126+ function unchecked_cld (x:: T , y:: T ) where T <: SignedBitInteger
127+ d = unchecked_div (x, y)
128+ return x == typemin (T) && y == - 1 || y == 0 ?
129+ d :
130+ d + (((x > 0 ) == (y > 0 )) & (d * y != x))
131+ end
132+ function unchecked_cld (x:: T , y:: T ) where T <: UnsignedBitInteger
133+ d = unchecked_div (x, y)
134+ return y == 0 ?
135+ d :
136+ d + (d * y != x)
137+ end
138+
139+ unchecked_rem (x:: T , y:: T ) where T <: SignedBitInteger =
140+ (y == zero (T)) ?
141+ x :
142+ (y == - one (T)) ?
143+ zero (T) :
144+ Base. srem_int (x, y)
145+ unchecked_rem (x:: T , y:: T ) where T <: UnsignedBitInteger =
146+ (y == zero (T)) ?
147+ x :
148+ Base. urem_int (x, y)
149+
150+ unchecked_mod (x:: T , y:: T ) where T <: SignedBitInteger = x - unchecked_fld (x, y) * y
151+ unchecked_mod (x:: T , y:: T ) where T <: UnsignedBitInteger = unchecked_rem (x, y)
152+
153+
69154if VERSION < v " 1.11"
70155# Base.Checked only gained checked powers in 1.11
71156
0 commit comments