@@ -50,6 +50,9 @@ function rawone(::Type{Fixed{T,f}}) where {T, f}
5050 oneunit (T) << f
5151end
5252
53+ intmask (:: Fixed{T,f} ) where {T, f} = - oneunit (T) << f # Signed
54+ fracmask (x:: Fixed{T,f} ) where {T, f} = ~ intmask (x) # Signed
55+
5356# unchecked arithmetic
5457
5558# with truncation:
9194(:: Type{TR} )(x:: Fixed{T,f} ) where {TR <: Rational ,T,f} =
9295 TR (x. i>> f + (x. i& (1 << f- 1 ))// (one (widen1 (T))<< f))
9396
97+ function trunc (x:: Fixed{T,f} ) where {T, f}
98+ f == 0 && return x
99+ f == bitwidth (T) && return zero (x) # TODO : remove this line
100+ f == bitwidth (T) - 1 && return x. i == typemin (T) ? x : zero (x)
101+ t = x. i & intmask (x)
102+ r = x. i & fracmask (x)
103+ _rawone = oneunit (T) << f
104+ reinterpret (Fixed{T,f}, (x. i < 0 ) & (r != 0 ) ? t + _rawone : t)
105+ end
106+ function floor (x:: Fixed{T,f} ) where {T, f}
107+ f == bitwidth (T) && x. i < 0 && throw_converterror (Fixed{T,f}, - 1 ) # TODO : remove this line
108+ Fixed {T,f} (x. i & intmask (x), 0 )
109+ end
110+ function ceil (x:: Fixed{T,f} ) where {T, f}
111+ f == 0 && return x
112+ upper = typemax (T) & intmask (x)
113+ x. i > upper && throw_converterror (Fixed{T,f}, ceil (float (x)))
114+ reinterpret (Fixed{T,f}, (x. i + fracmask (x)) & intmask (x))
115+ end
116+ function round (x:: Fixed{T,f} ) where {T, f}
117+ f == 0 && return x
118+ f == bitwidth (T) && return zero (x) # TODO : remove this line
119+ upper = intmask (x) >>> 0x1
120+ lower = intmask (x) >> 0x1
121+ if f == bitwidth (T) - 1
122+ x. i > upper && throw_converterror (Fixed{T,f}, @exp2 (bitwidth (T)- f- 1 ))
123+ return x. i < lower ? typemin (x) : zero (x)
124+ end
125+ x. i >= upper && throw_converterror (Fixed{T,f}, @exp2 (bitwidth (T)- f- 1 ))
126+ y = oneunit (T) << UInt8 (f - 1 ) + x. i
127+ m = oneunit (T) << UInt8 (f + 1 ) - oneunit (T)
128+ z = y & intmask (x)
129+ reinterpret (Fixed{T,f}, z - T (y & m == rawone (x)) << f)
130+ end
131+
132+ function trunc (:: Type{Ti} , x:: Fixed{T,f} ) where {Ti <: Integer , T, f}
133+ f == 0 && return convert (Ti, x. i)
134+ f == bitwidth (T) && return zero (Ti) # TODO : remove this line
135+ f == bitwidth (T) - 1 && return x. i == typemin (T) ? convert (Ti, - 1 ) : zero (Ti)
136+ t = x. i >> f
137+ r = x. i & fracmask (x)
138+ convert (Ti, (x. i < 0 ) & (r != 0 ) ? t + oneunit (T) : t)
139+ end
140+ function floor (:: Type{Ti} , x:: Fixed{T,f} ) where {Ti <: Integer , T, f}
141+ f == bitwidth (T) && return x. i < 0 ? convert (Ti, - 1 ) : zero (Ti) # TODO : remove this line
142+ convert (Ti, x. i >> f)
143+ end
144+ function ceil (:: Type{Ti} , x:: Fixed{T,f} ) where {Ti <: Integer , T, f}
145+ f == bitwidth (T) && return x. i > 0 ? oneunit (Ti) : zero (Ti) # TODO : remove this line
146+ y = x. i + fracmask (x)
147+ convert (Ti, x. i >= 0 ? y >>> f : y >> f)
148+ end
149+ function round (:: Type{Ti} , x:: Fixed{T,f} ) where {Ti <: Integer , T, f}
150+ f == 0 && return convert (Ti, x. i)
151+ f == bitwidth (T) && return zero (Ti) # TODO : remove this line
152+ upper = intmask (x) >>> 0x1
153+ lower = intmask (x) >> 0x1
154+ if f == bitwidth (T) - 1
155+ x. i < lower && return convert (Ti, - 1 )
156+ return x. i > upper ? oneunit (Ti) : zero (Ti)
157+ end
158+ y = oneunit (T) << UInt8 (f - 1 ) + x. i
159+ m = oneunit (T) << UInt8 (f + 1 ) - oneunit (T)
160+ z = x. i >= 0 ? y >>> f : y >> f
161+ convert (Ti, z - Ti (y & m == rawone (x)))
162+ end
163+
94164promote_rule (ft:: Type{Fixed{T,f}} , :: Type{TI} ) where {T,f,TI <: Integer } = Fixed{T,f}
95165promote_rule (:: Type{Fixed{T,f}} , :: Type{TF} ) where {T,f,TF <: AbstractFloat } = TF
96166promote_rule (:: Type{Fixed{T,f}} , :: Type{Rational{TR}} ) where {T,f,TR} = Rational{TR}
0 commit comments