@@ -44,6 +44,9 @@ function rawone(::Type{Fixed{T,f}}) where {T, f}
4444 oneunit (T) << f
4545end
4646
47+ intmask (:: Fixed{T,f} ) where {T, f} = - oneunit (T) << f # Signed
48+ fracmask (x:: Fixed{T,f} ) where {T, f} = ~ intmask (x) # Signed
49+
4750# unchecked arithmetic
4851
4952# with truncation:
8588(:: Type{TR} )(x:: Fixed{T,f} ) where {TR <: Rational ,T,f} =
8689 TR (x. i>> f + (x. i& (1 << f- 1 ))// (one (widen1 (T))<< f))
8790
91+ function trunc (x:: Fixed{T,f} ) where {T, f}
92+ f == 0 && return x
93+ f == bitwidth (T) && return zero (x)
94+ f == bitwidth (T) - 1 && return x. i == typemin (T) ? x : zero (x)
95+ t = x. i & intmask (x)
96+ r = x. i & fracmask (x)
97+ _rawone = oneunit (T) << f
98+ reinterpret (Fixed{T,f}, (x. i < 0 ) & (r != 0 ) ? t + _rawone : t)
99+ end
100+ function floor (x:: Fixed{T,f} ) where {T, f}
101+ f == bitwidth (T) && x. i < 0 && throw_converterror (Fixed{T,f}, - 1 )
102+ Fixed {T,f} (x. i & intmask (x), 0 )
103+ end
104+ function ceil (x:: Fixed{T,f} ) where {T, f}
105+ f == 0 && return x
106+ upper = typemax (T) & intmask (x)
107+ x. i > upper && throw_converterror (Fixed{T,f}, ceil (float (x)))
108+ reinterpret (Fixed{T,f}, (x. i + fracmask (x)) & intmask (x))
109+ end
110+ function round (x:: Fixed{T,f} ) where {T, f}
111+ f == 0 && return x
112+ f == bitwidth (T) && return zero (x)
113+ upper = intmask (x) >>> 0x1
114+ lower = intmask (x) >> 0x1
115+ if f == bitwidth (T) - 1
116+ x. i > upper && throw_converterror (Fixed{T,f}, @exp2 (bitwidth (T)- f- 1 ))
117+ return x. i < lower ? typemin (x) : zero (x)
118+ end
119+ x. i >= upper && throw_converterror (Fixed{T,f}, @exp2 (bitwidth (T)- f- 1 ))
120+ y = oneunit (T) << UInt8 (f - 1 ) + x. i
121+ m = oneunit (T) << UInt8 (f + 1 ) - oneunit (T)
122+ z = y & intmask (x)
123+ reinterpret (Fixed{T,f}, z - T (y & m == rawone (x)) << f)
124+ end
125+
126+ function trunc (:: Type{Ti} , x:: Fixed{T,f} ) where {Ti <: Integer , T, f}
127+ f == 0 && return convert (Ti, x. i)
128+ f == bitwidth (T) && return zero (Ti)
129+ f == bitwidth (T) - 1 && return x. i == typemin (T) ? convert (Ti, - 1 ) : zero (Ti)
130+ t = x. i >> f
131+ r = x. i & fracmask (x)
132+ convert (Ti, (x. i < 0 ) & (r != 0 ) ? t + oneunit (T) : t)
133+ end
134+ function floor (:: Type{Ti} , x:: Fixed{T,f} ) where {Ti <: Integer , T, f}
135+ f == bitwidth (T) && return x. i < 0 ? convert (Ti, - 1 ) : zero (Ti)
136+ convert (Ti, x. i >> f)
137+ end
138+ function ceil (:: Type{Ti} , x:: Fixed{T,f} ) where {Ti <: Integer , T, f}
139+ f == bitwidth (T) && return x. i > 0 ? oneunit (Ti) : zero (Ti)
140+ y = x. i + fracmask (x)
141+ convert (Ti, x. i >= 0 ? y >>> f : y >> f)
142+ end
143+ function round (:: Type{Ti} , x:: Fixed{T,f} ) where {Ti <: Integer , T, f}
144+ f == 0 && return convert (Ti, x. i)
145+ f == bitwidth (T) && return zero (Ti)
146+ upper = intmask (x) >>> 0x1
147+ lower = intmask (x) >> 0x1
148+ if f == bitwidth (T) - 1
149+ x. i < lower && return convert (Ti, - 1 )
150+ return x. i > upper ? oneunit (Ti) : zero (Ti)
151+ end
152+ y = oneunit (T) << UInt8 (f - 1 ) + x. i
153+ m = oneunit (T) << UInt8 (f + 1 ) - oneunit (T)
154+ z = x. i >= 0 ? y >>> f : y >> f
155+ convert (Ti, z - Ti (y & m == rawone (x)))
156+ end
157+
88158promote_rule (ft:: Type{Fixed{T,f}} , :: Type{TI} ) where {T,f,TI <: Integer } = Fixed{T,f}
89159promote_rule (:: Type{Fixed{T,f}} , :: Type{TF} ) where {T,f,TF <: AbstractFloat } = TF
90160promote_rule (:: Type{Fixed{T,f}} , :: Type{Rational{TR}} ) where {T,f,TR} = Rational{TR}
0 commit comments