@@ -9,7 +9,9 @@ immutable UFixed{T<:Unsigned,f} <: FixedPoint{T,f}
9
9
end
10
10
11
11
rawtype {T,f} (:: Type{UFixed{T,f}} ) = T
12
+ rawtype (x:: Number ) = rawtype (typeof (x))
12
13
nbitsfrac {T,f} (:: Type{UFixed{T,f}} ) = f
14
+ nbitsfrac (x:: Number ) = nbitsfract (typeof (x))
13
15
14
16
typealias UFixed8 UFixed{UInt8,8 }
15
17
typealias UFixed10 UFixed{UInt16,10 }
@@ -31,29 +33,40 @@ const uf14 = UFixedConstructor{UInt16,14}()
31
33
const uf16 = UFixedConstructor {UInt16,16} ()
32
34
33
35
zero {T,f} (:: Type{UFixed{T,f}} ) = UFixed {T,f} (zero (T),0 )
34
- @generated function one {T<:UFixed} (:: Type{T} )
35
- f = 2 ^ nbitsfrac (T)- 1
36
- :( T ($ f,0 ) )
36
+ function one {T<:UFixed} (:: Type{T} )
37
+ T (typemax (rawtype (T)) >> (8 * sizeof (T)- nbitsfrac (T)), 0 )
37
38
end
38
39
zero (x:: UFixed ) = zero (typeof (x))
39
40
one (x:: UFixed ) = one (typeof (x))
40
41
rawone (v) = reinterpret (one (v))
41
42
42
43
# Conversions
43
44
convert {T<:UFixed} (:: Type{T} , x:: T ) = x
44
- convert {T1<:UFixed} (:: Type{T1} , x:: UFixed ) = reinterpret (T1, round (rawtype (T1), (rawone (T1)/ rawone (x))* reinterpret (x)))
45
+ function convert {T<:UFixed} (:: Type{T} , x:: UFixed )
46
+ y = round ((rawone (T)/ rawone (x))* reinterpret (x))
47
+ (0 <= y) & (y <= typemax (rawtype (T))) || throw_converterror (T, x)
48
+ reinterpret (T, _unsafe_trunc (rawtype (T), y))
49
+ end
45
50
convert (:: Type{UFixed16} , x:: UFixed8 ) = reinterpret (UFixed16, convert (UInt16, 0x0101 * reinterpret (x)))
46
51
convert {U<:UFixed} (:: Type{U} , x:: Real ) = _convert (U, rawtype (U), x)
47
- _convert {U<:UFixed,T} (:: Type{U} , :: Type{T} , x) = U (round (T, widen1 (rawone (U))* x), 0 )
48
- _convert {U<:UFixed } (:: Type{U} , :: Type{UInt128} , x) = U (round (UInt128, rawone (U)* x), 0 )
52
+ function _convert {U<:UFixed,T} (:: Type{U} , :: Type{T} , x)
53
+ y = round (widen1 (rawone (U))* x)
54
+ (0 <= y) & (y <= typemax (T)) || throw_converterror (U, x)
55
+ U (_unsafe_trunc (T, y), 0 )
56
+ end
57
+ function _convert {U<:UFixed} (:: Type{U} , :: Type{UInt128} , x)
58
+ y = round (rawone (U)* x) # for UInt128, we can't widen
59
+ (0 <= y) & (y <= typemax (UInt128)) & (x <= Float64 (typemax (U))) || throw_converterror (U, x)
60
+ U (_unsafe_trunc (UInt128, y), 0 )
61
+ end
49
62
50
63
rem {T<:UFixed} (x:: T , :: Type{T} ) = x
51
- rem {T<:UFixed} (x:: UFixed , :: Type{T} ) = reinterpret (T, unsafe_trunc (rawtype (T), round ((rawone (T)/ rawone (x))* reinterpret (x))))
52
- rem {T<:UFixed} (x:: Real , :: Type{T} ) = reinterpret (T, unsafe_trunc (rawtype (T), round (rawone (T)* x)))
64
+ rem {T<:UFixed} (x:: UFixed , :: Type{T} ) = reinterpret (T, _unsafe_trunc (rawtype (T), round ((rawone (T)/ rawone (x))* reinterpret (x))))
65
+ rem {T<:UFixed} (x:: Real , :: Type{T} ) = reinterpret (T, _unsafe_trunc (rawtype (T), round (rawone (T)* x)))
53
66
54
67
convert (:: Type{BigFloat} , x:: UFixed ) = reinterpret (x)* (1 / BigFloat (rawone (x)))
55
68
function convert {T<:AbstractFloat} (:: Type{T} , x:: UFixed )
56
- y = reinterpret (x)* (1 / convert (T, rawone (x)))
69
+ y = reinterpret (x)* (one ( rawtype (x)) / convert (T, rawone (x)))
57
70
convert (T, y) # needed for types like Float16 which promote arithmetic to Float32
58
71
end
59
72
convert (:: Type{Bool} , x:: UFixed ) = x == zero (x) ? false : true
@@ -68,17 +81,21 @@ sizeof{T<:UFixed}(::Type{T}) = sizeof(rawtype(T))
68
81
abs (x:: UFixed ) = x
69
82
70
83
# Arithmetic
84
+ @generated function floattype {U<:UFixed} (:: Type{U} )
85
+ eps (U) < eps (Float32) ? :(Float64) : :(Float32)
86
+ end
87
+
71
88
(- ){T<: UFixed }(x:: T ) = T (- reinterpret (x), 0 )
72
89
(~ ){T<: UFixed }(x:: T ) = T (~ reinterpret (x), 0 )
73
90
74
91
+ {T,f}(x:: UFixed{T,f} , y:: UFixed{T,f} ) = UFixed {T,f} (convert (T, x. i+ y. i),0 )
75
92
- {T,f}(x:: UFixed{T,f} , y:: UFixed{T,f} ) = UFixed {T,f} (convert (T, x. i- y. i),0 )
76
- * {T<: UFixed }(x:: T , y:: T ) = convert (T,convert (Float32 , x)* convert (Float32 , y))
77
- / {T<: UFixed }(x:: T , y:: T ) = convert (T,convert (Float32 , x)/ convert (Float32 , y))
93
+ * {T<: UFixed }(x:: T , y:: T ) = convert (T,convert (floattype (T) , x)* convert (floattype (T) , y))
94
+ / {T<: UFixed }(x:: T , y:: T ) = convert (T,convert (floattype (T) , x)/ convert (floattype (T) , y))
78
95
79
96
# Comparisons
80
97
< {T<: UFixed }(x:: T , y:: T ) = reinterpret (x) < reinterpret (y)
81
- <= {T<: UFixed }(x:: T , y:: T ) = reinterpret (x) < reinterpret (y)
98
+ <= {T<: UFixed }(x:: T , y:: T ) = reinterpret (x) <= reinterpret (y)
82
99
83
100
# Functions
84
101
trunc {T<:UFixed} (x:: T ) = T (div (reinterpret (x), rawone (T))* rawone (T),0 )
@@ -150,3 +167,18 @@ promote_rule{T<:UFixed, R<:Rational}(::Type{T}, ::Type{R}) = R
150
167
Tp = eps (convert (Float32, typemax (Ti))) > eps (T) ? Float64 : Float32
151
168
:( $ Tp )
152
169
end
170
+ @generated function promote_rule {T1,T2,f1,f2} (:: Type{UFixed{T1,f1}} , :: Type{UFixed{T2,f2}} )
171
+ f = max (f1, f2) # ensure we have enough precision
172
+ T = promote_type (T1, T2)
173
+ # make sure we have enough integer bits
174
+ i1, i2 = 8 * sizeof (T1)- f1, 8 * sizeof (T2)- f2 # number of integer bits for each
175
+ i = 8 * sizeof (T)- f
176
+ while i < max (i1, i2)
177
+ T = widen1 (T)
178
+ i = 8 * sizeof (T)- f
179
+ end
180
+ :(UFixed{$ T,$ f})
181
+ end
182
+
183
+ _unsafe_trunc {T} (:: Type{T} , x:: Integer ) = x % T
184
+ _unsafe_trunc {T} (:: Type{T} , x) = unsafe_trunc (T, x)
0 commit comments