@@ -44,6 +44,9 @@ function rawone(::Type{Fixed{T,f}}) where {T, f}
44
44
oneunit (T) << f
45
45
end
46
46
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
+
47
50
# unchecked arithmetic
48
51
49
52
# with truncation:
85
88
(:: Type{TR} )(x:: Fixed{T,f} ) where {TR <: Rational ,T,f} =
86
89
TR (x. i>> f + (x. i& (1 << f- 1 ))// (one (widen1 (T))<< f))
87
90
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
+
88
158
promote_rule (ft:: Type{Fixed{T,f}} , :: Type{TI} ) where {T,f,TI <: Integer } = Fixed{T,f}
89
159
promote_rule (:: Type{Fixed{T,f}} , :: Type{TF} ) where {T,f,TF <: AbstractFloat } = TF
90
160
promote_rule (:: Type{Fixed{T,f}} , :: Type{Rational{TR}} ) where {T,f,TR} = Rational{TR}
0 commit comments