@@ -95,19 +95,20 @@ function _convert(::Type{F}, x::Rational) where {T, f, F <: Fixed{T,f}}
95
95
end
96
96
end
97
97
98
- # unchecked arithmetic
99
-
100
- # with truncation:
101
- # *(x::Fixed{T,f}, y::Fixed{T,f}) = Fixed{T,f}(Base.widemul(x.i,y.i)>>f,0)
102
- # with rounding up:
103
- * (x:: Fixed{T,f} , y:: Fixed{T,f} ) where {T,f} = Fixed {T,f} ((Base. widemul (x. i,y. i) + (one (widen (T)) << (f- 1 )))>> f,0 )
104
-
105
- / (x:: Fixed{T,f} , y:: Fixed{T,f} ) where {T,f} = Fixed {T,f} (div (convert (widen (T), x. i) << f, y. i), 0 )
106
-
107
-
108
- rem (x:: Integer , :: Type{Fixed{T,f}} ) where {T,f} = Fixed {T,f} (rem (x,T)<< f,0 )
109
- rem (x:: Real , :: Type{Fixed{T,f}} ) where {T,f} = Fixed {T,f} (rem (Integer (trunc (x)),T)<< f + rem (Integer (round (rem (x,1 )* (one (widen1 (T))<< f))),T),0 )
110
-
98
+ rem (x:: F , :: Type{F} ) where {F <: Fixed } = x
99
+ function rem (x:: Fixed , :: Type{F} ) where {T, f, F <: Fixed{T,f} }
100
+ f2 = nbitsfrac (typeof (x))
101
+ y = round (@exp2 (f - f2) * reinterpret (x))
102
+ reinterpret (F, _unsafe_trunc (T, y))
103
+ end
104
+ rem (x:: Integer , :: Type{F} ) where {T, f, F <: Fixed{T,f} } = F (_unsafe_trunc (T, x) << f, 0 )
105
+ function rem (x:: Real , :: Type{F} ) where {T, f, F <: Fixed{T,f} }
106
+ y = _unsafe_trunc (promote_type (Int64, T), round (x * @exp2 (f)))
107
+ reinterpret (F, _unsafe_trunc (T, y))
108
+ end
109
+ function rem (x:: BigFloat , :: Type{F} ) where {T, f, F <: Fixed{T,f} }
110
+ reinterpret (F, _unsafe_trunc (T, round (x * @exp2 (f))))
111
+ end
111
112
112
113
(:: Type{Tf} )(x:: Fixed{T,f} ) where {Tf <: AbstractFloat , T, f} = Tf (Tf (x. i) * Tf (@exp2 (- f)))
113
114
Base. Float16 (x:: Fixed{T,f} ) where {T, f} = Float16 (Float32 (x))
@@ -118,6 +119,60 @@ function Base.Rational(x::Fixed{T,f}) where {T, f}
118
119
f < bitwidth (T)- 1 ? x. i// rawone (x) : x. i// (one (widen1 (T))<< f)
119
120
end
120
121
122
+ function div_2f (x:: T , :: Val{f} ) where {T, f}
123
+ xf = x & (T (- 1 ) >>> (bitwidth (T) - f - 1 ))
124
+ half = oneunit (T) << (f - 1 )
125
+ c = half - (xf === half)
126
+ (x + c) >> f
127
+ end
128
+ div_2f (x:: T , :: Val{0} ) where {T} = x
129
+
130
+ # wrapping arithmetic
131
+ function wrapping_mul (x:: F , y:: F ) where {T <: Union{Int8,Int16,Int32,Int64} , f, F <: Fixed{T,f} }
132
+ z = widemul (x. i, y. i)
133
+ F (div_2f (z, Val (Int (f))) % T, 0 )
134
+ end
135
+
136
+ # saturating arithmetic
137
+ function saturating_mul (x:: F , y:: F ) where {T <: Union{Int8,Int16,Int32,Int64} , f, F <: Fixed{T,f} }
138
+ if f >= bitwidth (T) - 1
139
+ z = min (widemul (x. i, y. i), widen1 (typemax (T)) << f)
140
+ else
141
+ z = clamp (widemul (x. i, y. i), widen1 (typemin (T)) << f, widen1 (typemax (T)) << f)
142
+ end
143
+ F (div_2f (z, Val (Int (f))) % T, 0 )
144
+ end
145
+
146
+ # checked arithmetic
147
+ function checked_mul (x:: F , y:: F ) where {T <: Union{Int8,Int16,Int32,Int64} , f, F <: Fixed{T,f} }
148
+ z = widemul (x. i, y. i)
149
+ if f < 1
150
+ m = widen1 (typemax (T)) + 0x1
151
+ n = widen1 (typemin (T))
152
+ else
153
+ half = widen1 (oneunit (T)) << (f - 1 )
154
+ m = widen1 (typemax (T)) << f + half
155
+ n = widen1 (typemin (T)) << f - half
156
+ end
157
+ (n <= z) & (z < m) || throw_overflowerror (:* , x, y)
158
+ F (div_2f (z, Val (Int (f))) % T, 0 )
159
+ end
160
+
161
+ function mul_with_rounding (x:: F , y:: F , :: RoundingMode{:Nearest} ) where {F <: Fixed }
162
+ wrapping_mul (x, y)
163
+ end
164
+ function mul_with_rounding (x:: F , y:: F , :: RoundingMode{:NearestTiesUp} ) where
165
+ {T <: Union{Int8,Int16,Int32,Int64} , f, F <: Fixed{T, f} }
166
+ z = widemul (x. i, y. i)
167
+ F (((z + (oftype (z, 1 ) << f >>> 1 )) >> f) % T, 0 )
168
+ end
169
+ function mul_with_rounding (x:: F , y:: F , :: RoundingMode{:Down} ) where
170
+ {T <: Union{Int8,Int16,Int32,Int64} , f, F <: Fixed{T, f} }
171
+ F ((widemul (x. i, y. i) >> f) % T, 0 )
172
+ end
173
+
174
+ / (x:: Fixed{T,f} , y:: Fixed{T,f} ) where {T,f} = Fixed {T,f} (div (convert (widen (T), x. i) << f, y. i), 0 )
175
+
121
176
function trunc (x:: Fixed{T,f} ) where {T, f}
122
177
f == 0 && return x
123
178
f == bitwidth (T) && return zero (x) # TODO : remove this line
0 commit comments