Skip to content

Commit 526a7b9

Browse files
committed
Fix issues with UInt128 and high-precision UFixed types
1 parent 77d1585 commit 526a7b9

File tree

2 files changed

+17
-9
lines changed

2 files changed

+17
-9
lines changed

src/ufixed.jl

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ immutable UFixed{T<:Unsigned,f} <: FixedPoint{T,f}
99
end
1010

1111
rawtype{T,f}(::Type{UFixed{T,f}}) = T
12+
rawtype(x::Number) = rawtype(typeof(x))
1213
nbitsfrac{T,f}(::Type{UFixed{T,f}}) = f
14+
nbitsfrac(x::Number) = nbitsfract(typeof(x))
1315

1416
typealias UFixed8 UFixed{UInt8,8}
1517
typealias UFixed10 UFixed{UInt16,10}
@@ -31,9 +33,8 @@ const uf14 = UFixedConstructor{UInt16,14}()
3133
const uf16 = UFixedConstructor{UInt16,16}()
3234

3335
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)
3738
end
3839
zero(x::UFixed) = zero(typeof(x))
3940
one(x::UFixed) = one(typeof(x))
@@ -65,7 +66,7 @@ rem{T<:UFixed}(x::Real, ::Type{T}) = reinterpret(T, _unsafe_trunc(rawtype(T), ro
6566

6667
convert(::Type{BigFloat}, x::UFixed) = reinterpret(x)*(1/BigFloat(rawone(x)))
6768
function convert{T<:AbstractFloat}(::Type{T}, x::UFixed)
68-
y = reinterpret(x)*(1/convert(T, rawone(x)))
69+
y = reinterpret(x)*(one(rawtype(x))/convert(T, rawone(x)))
6970
convert(T, y) # needed for types like Float16 which promote arithmetic to Float32
7071
end
7172
convert(::Type{Bool}, x::UFixed) = x == zero(x) ? false : true
@@ -80,13 +81,17 @@ sizeof{T<:UFixed}(::Type{T}) = sizeof(rawtype(T))
8081
abs(x::UFixed) = x
8182

8283
# Arithmetic
84+
@generated function floattype{U<:UFixed}(::Type{U})
85+
eps(U) < eps(Float32) ? :(Float64) : :(Float32)
86+
end
87+
8388
(-){T<:UFixed}(x::T) = T(-reinterpret(x), 0)
8489
(~){T<:UFixed}(x::T) = T(~reinterpret(x), 0)
8590

8691
+{T,f}(x::UFixed{T,f}, y::UFixed{T,f}) = UFixed{T,f}(convert(T, x.i+y.i),0)
8792
-{T,f}(x::UFixed{T,f}, y::UFixed{T,f}) = UFixed{T,f}(convert(T, x.i-y.i),0)
88-
*{T<:UFixed}(x::T, y::T) = convert(T,convert(Float32, x)*convert(Float32, y))
89-
/{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))
9095

9196
# Comparisons
9297
<{T<:UFixed}(x::T, y::T) = reinterpret(x) < reinterpret(y)

test/ufixed.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ v = @compat UFixed12.([2])
2121
@test v == UFixed12[0x1ffeuf12]
2222
@test isa(v, Vector{UFixed12})
2323

24-
UF2 = (UFixed{UInt32,16}, UFixed{UInt64,3}, UFixed{UInt128,7})
24+
UF2 = (UFixed{UInt32,16}, UFixed{UInt64,3}, UFixed{UInt64,51}, UFixed{UInt128,7}, UFixed{UInt128,51})
2525

2626
for T in (FixedPointNumbers.UF..., UF2...)
2727
@test zero(T) == 0
@@ -43,6 +43,7 @@ end
4343
@test typemax(UFixed{UInt32,16}) == typemax(UInt32) // (2^16-1)
4444
@test typemax(UFixed{UInt64,3}) == typemax(UInt64) // (2^3-1)
4545
@test typemax(UFixed{UInt128,7}) == typemax(UInt128) // (2^7-1)
46+
@test typemax(UFixed{UInt128,100}) == typemax(UInt128) // (UInt128(2)^100-1)
4647

4748
# TODO: change back to InexactError when it allows message strings
4849
@test_throws ArgumentError UFixed8(2)
@@ -53,6 +54,8 @@ end
5354
@test_throws ArgumentError UFixed16(0xffff)
5455
@test_throws ArgumentError convert(UFixed8, typemax(UFixed10))
5556
@test_throws ArgumentError convert(UFixed16, typemax(UFixed10))
57+
@test_throws ArgumentError convert(UFixed{UInt128,100}, 10^9)
58+
@test_throws ArgumentError convert(UFixed{UInt128,100}, 10.0^9)
5659

5760
x = UFixed8(0.5)
5861
@test isfinite(x) == true
@@ -104,8 +107,8 @@ x = UFixed8(0b01010001, 0)
104107
for T in (FixedPointNumbers.UF..., UF2...)
105108
x = T(0x10,0)
106109
y = T(0x25,0)
107-
fx = convert(Float32, x)
108-
fy = convert(Float32, y)
110+
fx = convert(FixedPointNumbers.floattype(T), x)
111+
fy = convert(FixedPointNumbers.floattype(T), y)
109112
@test y > x
110113
@test y != x
111114
@test typeof(x+y) == T

0 commit comments

Comments
 (0)