Skip to content

Commit ef03354

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

File tree

2 files changed

+14
-6
lines changed

2 files changed

+14
-6
lines changed

src/ufixed.jl

Lines changed: 10 additions & 3 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}
@@ -35,6 +37,7 @@ zero{T,f}(::Type{UFixed{T,f}}) = UFixed{T,f}(zero(T),0)
3537
f = 2^nbitsfrac(T)-1
3638
:( T($f,0) )
3739
end
40+
one{f}(::Type{UFixed{UInt128,f}}) = UFixed{UInt128,f}(UInt128(2)^f-1, 0)
3841
zero(x::UFixed) = zero(typeof(x))
3942
one(x::UFixed) = one(typeof(x))
4043
rawone(v) = reinterpret(one(v))
@@ -65,7 +68,7 @@ rem{T<:UFixed}(x::Real, ::Type{T}) = reinterpret(T, _unsafe_trunc(rawtype(T), ro
6568

6669
convert(::Type{BigFloat}, x::UFixed) = reinterpret(x)*(1/BigFloat(rawone(x)))
6770
function convert{T<:AbstractFloat}(::Type{T}, x::UFixed)
68-
y = reinterpret(x)*(1/convert(T, rawone(x)))
71+
y = reinterpret(x)*(one(rawtype(x))/convert(T, rawone(x)))
6972
convert(T, y) # needed for types like Float16 which promote arithmetic to Float32
7073
end
7174
convert(::Type{Bool}, x::UFixed) = x == zero(x) ? false : true
@@ -80,13 +83,17 @@ sizeof{T<:UFixed}(::Type{T}) = sizeof(rawtype(T))
8083
abs(x::UFixed) = x
8184

8285
# Arithmetic
86+
@generated function floattype{U<:UFixed}(::Type{U})
87+
eps(U) < eps(Float32) ? :(Float64) : :(Float32)
88+
end
89+
8390
(-){T<:UFixed}(x::T) = T(-reinterpret(x), 0)
8491
(~){T<:UFixed}(x::T) = T(~reinterpret(x), 0)
8592

8693
+{T,f}(x::UFixed{T,f}, y::UFixed{T,f}) = UFixed{T,f}(convert(T, x.i+y.i),0)
8794
-{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))
95+
*{T<:UFixed}(x::T, y::T) = convert(T,convert(floattype(T), x)*convert(floattype(T), y))
96+
/{T<:UFixed}(x::T, y::T) = convert(T,convert(floattype(T), x)/convert(floattype(T), y))
9097

9198
# Comparisons
9299
<{T<:UFixed}(x::T, y::T) = reinterpret(x) < reinterpret(y)

test/ufixed.jl

Lines changed: 4 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)
@@ -104,8 +105,8 @@ x = UFixed8(0b01010001, 0)
104105
for T in (FixedPointNumbers.UF..., UF2...)
105106
x = T(0x10,0)
106107
y = T(0x25,0)
107-
fx = convert(Float32, x)
108-
fy = convert(Float32, y)
108+
fx = convert(FixedPointNumbers.floattype(T), x)
109+
fy = convert(FixedPointNumbers.floattype(T), y)
109110
@test y > x
110111
@test y != x
111112
@test typeof(x+y) == T

0 commit comments

Comments
 (0)