@@ -9,7 +9,9 @@ immutable UFixed{T<:Unsigned,f} <: FixedPoint{T,f}
99end
1010
1111 rawtype {T,f} (:: Type{UFixed{T,f}} ) = T
12+ rawtype (x:: Number ) = rawtype (typeof (x))
1213nbitsfrac {T,f} (:: Type{UFixed{T,f}} ) = f
14+ nbitsfrac (x:: Number ) = nbitsfract (typeof (x))
1315
1416typealias UFixed8 UFixed{UInt8,8 }
1517typealias UFixed10 UFixed{UInt16,10 }
@@ -31,29 +33,40 @@ const uf14 = UFixedConstructor{UInt16,14}()
3133const uf16 = UFixedConstructor {UInt16,16} ()
3234
3335zero {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 )
3738end
3839zero (x:: UFixed ) = zero (typeof (x))
3940 one (x:: UFixed ) = one (typeof (x))
4041rawone (v) = reinterpret (one (v))
4142
4243# Conversions
4344convert {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
4550convert (:: Type{UFixed16} , x:: UFixed8 ) = reinterpret (UFixed16, convert (UInt16, 0x0101 * reinterpret (x)))
4651convert {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
4962
5063rem {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)))
5366
5467convert (:: Type{BigFloat} , x:: UFixed ) = reinterpret (x)* (1 / BigFloat (rawone (x)))
5568function 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)))
5770 convert (T, y) # needed for types like Float16 which promote arithmetic to Float32
5871end
5972convert (:: Type{Bool} , x:: UFixed ) = x == zero (x) ? false : true
@@ -68,17 +81,21 @@ sizeof{T<:UFixed}(::Type{T}) = sizeof(rawtype(T))
6881abs (x:: UFixed ) = x
6982
7083# Arithmetic
84+ @generated function floattype {U<:UFixed} (:: Type{U} )
85+ eps (U) < eps (Float32) ? :(Float64) : :(Float32)
86+ end
87+
7188(- ){T<: UFixed }(x:: T ) = T (- reinterpret (x), 0 )
7289(~ ){T<: UFixed }(x:: T ) = T (~ reinterpret (x), 0 )
7390
7491+ {T,f}(x:: UFixed{T,f} , y:: UFixed{T,f} ) = UFixed {T,f} (convert (T, x. i+ y. i),0 )
7592- {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))
7895
7996# Comparisons
8097 < {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)
8299
83100# Functions
84101trunc {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
150167 Tp = eps (convert (Float32, typemax (Ti))) > eps (T) ? Float64 : Float32
151168 :( $ Tp )
152169end
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