@@ -12,7 +12,7 @@ import Base: ==, <, <=, -, +, *, /, ~, isapprox,
1212import Statistics # for _mean_promote
1313import Random: Random, AbstractRNG, SamplerType, rand!
1414
15- using Base. Checked: checked_add, checked_sub, checked_div
15+ import Base. Checked: checked_neg, checked_add, checked_sub, checked_div
1616
1717using Base: @pure
1818
3535# "special" typealiases
3636 # Q and N typealiases are exported in separate source files
3737# Functions
38- scaledual
38+ scaledual,
39+ wrapping_neg, wrapping_add, wrapping_sub,
40+ saturating_neg, saturating_add, saturating_sub
3941
4042include (" utilities.jl" )
4143
@@ -180,6 +182,49 @@ floattype(::Type{Base.TwicePrecision{T}}) where T<:Union{Float16,Float32} = wide
180182
181183float (x:: FixedPoint ) = convert (floattype (x), x)
182184
185+ # wrapping arithmetic
186+ wrapping_neg (x:: X ) where {X <: FixedPoint } = X (- x. i, 0 )
187+ wrapping_add (x:: X , y:: X ) where {X <: FixedPoint } = X (x. i + y. i, 0 )
188+ wrapping_sub (x:: X , y:: X ) where {X <: FixedPoint } = X (x. i - y. i, 0 )
189+
190+ # saturating arithmetic
191+ saturating_neg (x:: X ) where {X <: FixedPoint } = X (~ min (x. i - true , x. i), 0 )
192+ saturating_neg (x:: X ) where {X <: FixedPoint{<:Unsigned} } = zero (X)
193+
194+ function saturating_add (x:: X , y:: X ) where {X <: FixedPoint }
195+ r, f = Base. Checked. add_with_overflow (x. i, y. i)
196+ ifelse (f, ifelse (y. i < 0 , typemin (X), typemax (X)), X (r, 0 ))
197+ end
198+ saturating_add (x:: X , y:: X ) where {X <: FixedPoint{<:Unsigned} } = X (x. i + min (~ x. i, y. i), 0 )
199+
200+ function saturating_sub (x:: X , y:: X ) where {X <: FixedPoint }
201+ r, f = Base. Checked. sub_with_overflow (x. i, y. i)
202+ ifelse (f, ifelse (y. i < 0 , typemax (X), typemin (X)), X (r, 0 ))
203+ end
204+ saturating_sub (x:: X , y:: X ) where {X <: FixedPoint{<:Unsigned} } = X (x. i - min (x. i, y. i), 0 )
205+
206+ # checked arithmetic
207+ checked_neg (x:: X ) where {X <: FixedPoint } = X (checked_neg (x. i), 0 )
208+ checked_add (x:: X , y:: X ) where {X <: FixedPoint } = X (checked_add (x. i, y. i), 0 )
209+ checked_sub (x:: X , y:: X ) where {X <: FixedPoint } = X (checked_sub (x. i, y. i), 0 )
210+
211+ # default arithmetic
212+ const DEFAULT_ARITHMETIC = :wrapping
213+
214+ for (op, name) in ((:- , :neg ), )
215+ f = Symbol (DEFAULT_ARITHMETIC, :_ , name)
216+ @eval begin
217+ $ op (x:: X ) where {X <: FixedPoint } = $ f (x)
218+ end
219+ end
220+ for (op, name) in ((:+ , :add ), (:- , :sub ))
221+ f = Symbol (DEFAULT_ARITHMETIC, :_ , name)
222+ @eval begin
223+ $ op (x:: X , y:: X ) where {X <: FixedPoint } = $ f (x, y)
224+ end
225+ end
226+
227+
183228function minmax (x:: X , y:: X ) where {X <: FixedPoint }
184229 a, b = minmax (reinterpret (x), reinterpret (y))
185230 X (a,0 ), X (b,0 )
@@ -229,12 +274,12 @@ for f in (:(==), :<, :<=, :div, :fld, :fld1)
229274 $ f (x:: X , y:: X ) where {X <: FixedPoint } = $ f (x. i, y. i)
230275 end
231276end
232- for f in (:- , : ~ , :abs )
277+ for f in (:~ , :abs )
233278 @eval begin
234279 $ f (x:: X ) where {X <: FixedPoint } = X ($ f (x. i), 0 )
235280 end
236281end
237- for f in (:+ , : - , : rem , :mod , :mod1 , :min , :max )
282+ for f in (:rem , :mod , :mod1 , :min , :max )
238283 @eval begin
239284 $ f (x:: X , y:: X ) where {X <: FixedPoint } = X ($ f (x. i, y. i), 0 )
240285 end
0 commit comments