@@ -50,6 +50,9 @@ function rawone(::Type{Fixed{T,f}}) where {T, f}
50
50
oneunit (T) << f
51
51
end
52
52
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
+
53
56
# unchecked arithmetic
54
57
55
58
# with truncation:
91
94
(:: Type{TR} )(x:: Fixed{T,f} ) where {TR <: Rational ,T,f} =
92
95
TR (x. i>> f + (x. i& (1 << f- 1 ))// (one (widen1 (T))<< f))
93
96
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
+
94
164
promote_rule (ft:: Type{Fixed{T,f}} , :: Type{TI} ) where {T,f,TI <: Integer } = Fixed{T,f}
95
165
promote_rule (:: Type{Fixed{T,f}} , :: Type{TF} ) where {T,f,TF <: AbstractFloat } = TF
96
166
promote_rule (:: Type{Fixed{T,f}} , :: Type{Rational{TR}} ) where {T,f,TR} = Rational{TR}
0 commit comments