Skip to content

Commit 7ec0087

Browse files
committed
Use widening in conversions. Fixes #21, fixes #37.
1 parent 1cecb19 commit 7ec0087

File tree

5 files changed

+32
-3
lines changed

5 files changed

+32
-3
lines changed

src/FixedPointNumbers.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ typemin{T<: FixedPoint}(::Type{T}) = T(typemin(rawtype(T)), 0)
5252
realmin{T<: FixedPoint}(::Type{T}) = typemin(T)
5353
realmax{T<: FixedPoint}(::Type{T}) = typemax(T)
5454

55+
widen1(::Type{Int8}) = Int16
56+
widen1(::Type{UInt8}) = UInt16
57+
widen1(::Type{Int16}) = Int32
58+
widen1(::Type{UInt16}) = UInt32
59+
widen1(::Type{Int32}) = Int64
60+
widen1(::Type{UInt32}) = UInt64
61+
widen1(::Type{Int64}) = Int128
62+
widen1(::Type{UInt64}) = UInt128
63+
widen1(x::Integer) = x % widen1(typeof(x))
64+
5565
include("fixed.jl")
5666
include("ufixed.jl")
5767
include("deprecations.jl")

src/fixed.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ abs{T,f}(x::Fixed{T,f}) = Fixed{T,f}(abs(x.i),0)
3030

3131

3232
# # conversions and promotions
33-
convert{T,f}(::Type{Fixed{T,f}}, x::Integer) = Fixed{T,f}(convert(T,x)<<f,0)
34-
convert{T,f}(::Type{Fixed{T,f}}, x::AbstractFloat) = Fixed{T,f}(trunc(T,x)<<f + round(T, rem(x,1)*(1<<f)),0)
33+
convert{T,f}(::Type{Fixed{T,f}}, x::Integer) = Fixed{T,f}(round(T, convert(widen1(T),x)<<f),0)
34+
convert{T,f}(::Type{Fixed{T,f}}, x::AbstractFloat) = Fixed{T,f}(round(T, trunc(widen1(T),x)<<f + rem(x,1)*(1<<f)),0)
3535
convert{T,f}(::Type{Fixed{T,f}}, x::Rational) = Fixed{T,f}(x.num)/Fixed{T,f}(x.den)
3636

3737
convert{T,f}(::Type{BigFloat}, x::Fixed{T,f}) =

src/ufixed.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ rawone(v) = reinterpret(one(v))
4343
convert{T<:UFixed}(::Type{T}, x::T) = x
4444
convert{T1<:UFixed}(::Type{T1}, x::UFixed) = reinterpret(T1, round(rawtype(T1), (rawone(T1)/rawone(x))*reinterpret(x)))
4545
convert(::Type{UFixed16}, x::UFixed8) = reinterpret(UFixed16, convert(UInt16, 0x0101*reinterpret(x)))
46-
convert{T<:UFixed}(::Type{T}, x::Real) = T(round(rawtype(T), rawone(T)*x),0)
46+
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)
4749

4850

4951
convert(::Type{BigFloat}, x::UFixed) = reinterpret(x)*(1/BigFloat(rawone(x)))

test/fixed.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ function test_fixed{T}(::Type{T}, f)
5050
end
5151
end
5252

53+
@test_approx_eq_eps convert(Fixed{Int8,7}, 0.8) 0.797 0.001
54+
@test_approx_eq_eps convert(Fixed{Int8,7}, 0.9) 0.898 0.001
55+
@test_throws InexactError convert(Fixed{Int8, 7}, 0.999)
56+
@test_throws InexactError convert(Fixed{Int8, 7}, 1.0)
57+
@test_throws InexactError convert(Fixed{Int8, 7}, 1)
58+
@test_throws InexactError convert(Fixed{Int8, 7}, 2)
59+
@test_throws InexactError convert(Fixed{Int8, 7}, 128)
60+
5361
for (TI, f) in [(Int8, 8), (Int16, 8), (Int16, 10), (Int32, 16)]
5462
T = Fixed{TI,f}
5563
println(" Testing $T")

test/ufixed.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ end
4444
@test typemax(UFixed{UInt64,3}) == typemax(UInt64) // (2^3-1)
4545
@test typemax(UFixed{UInt128,7}) == typemax(UInt128) // (2^7-1)
4646

47+
@test_throws InexactError UFixed8(2)
48+
@test_throws InexactError UFixed8(255)
49+
@test_throws InexactError UFixed8(0xff)
50+
@test_throws InexactError UFixed16(2)
51+
@test_throws InexactError UFixed16(0xff)
52+
@test_throws InexactError UFixed16(0xffff)
53+
@test_throws InexactError convert(UFixed8, typemax(UFixed10))
54+
@test_throws InexactError convert(UFixed16, typemax(UFixed10))
55+
4756
x = UFixed8(0.5)
4857
@test isfinite(x) == true
4958
@test isnan(x) == false

0 commit comments

Comments
 (0)