From 44a2e165b72a56a68b26a314f3bd1b82f65effd2 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 13 Aug 2016 07:00:06 +0900 Subject: [PATCH 1/2] replace for @eval loop with generic methods --- src/ufixed.jl | 57 +++++++++++++++++++++----------------------------- test/ufixed.jl | 10 ++++----- 2 files changed, 29 insertions(+), 38 deletions(-) diff --git a/src/ufixed.jl b/src/ufixed.jl index 4cc369d2..dd8606c0 100644 --- a/src/ufixed.jl +++ b/src/ufixed.jl @@ -19,11 +19,7 @@ typealias UFixed16 UFixed{UInt16,16} const UF = (UFixed8, UFixed10, UFixed12, UFixed14, UFixed16) -for (uf) in UF - T = rawtype(uf) - f = nbitsfrac(uf) - @eval reinterpret(::Type{UFixed{$T,$f}}, x::$T) = UFixed{$T,$f}(x, 0) -end +reinterpret{T<:Unsigned,f}(::Type{UFixed{T,f}}, x::T) = UFixed{T,f}(x, 0) # The next lines mimic the floating-point literal syntax "3.2f0" immutable UFixedConstructor{T,f} end @@ -35,14 +31,8 @@ const uf14 = UFixedConstructor{UInt16,14}() const uf16 = UFixedConstructor{UInt16,16}() zero{T,f}(::Type{UFixed{T,f}}) = UFixed{T,f}(zero(T),0) -for uf in UF - TT = rawtype(uf) - f = nbitsfrac(uf) - T = UFixed{TT,f} - @eval begin - one(::Type{$T}) = $T($(2^f-1),0) - end -end +one{T, f}(::Type{UFixed{T,f}}) = UFixed{T,f}(2^f-1,0) + zero(x::UFixed) = zero(typeof(x)) one(x::UFixed) = one(typeof(x)) rawone(v) = reinterpret(one(v)) @@ -98,16 +88,20 @@ abs(x::UFixed) = x # Functions trunc{T<:UFixed}(x::T) = T(div(reinterpret(x), rawone(T))*rawone(T),0) floor{T<:UFixed}(x::T) = trunc(x) -for T in UF - f = nbitsfrac(T) - R = rawtype(T) - roundmask = convert(R, 1<<(f-1)) - k = 8*sizeof(R)-f - ceilmask = (typemax(R)<>k - @eval begin - round(x::$T) = (y = trunc(x); return convert(rawtype($T), reinterpret(x)-reinterpret(y))&$roundmask>0 ? $T(y+one($T)) : y) - ceil(x::$T) = (y = trunc(x); return convert(rawtype($T), reinterpret(x)-reinterpret(y))&$ceilmask >0 ? $T(y+one($T)) : y) - end + +roundmask{T,f}(::Type{UFixed{T,f}}) = convert(T, 1<<(f-1)) +function ceilmask{T,f}(::Type{UFixed{T,f}}) + k = 8*sizeof(T)-f + return (typemax(T)<>k +end + +function round{T<:UFixed}(x::T) + y = trunc(x) + return convert(rawtype(T), reinterpret(x)-reinterpret(y))&roundmask(T)>0 ? T(y+one(T)) : y +end +function ceil{T<:UFixed}(x::T) + y = trunc(x) + return convert(rawtype(T), reinterpret(x)-reinterpret(y))&ceilmask(T)>0 ? T(y+one(T)) : y end trunc{T<:Integer}(::Type{T}, x::UFixed) = convert(T, div(reinterpret(x), rawone(x))) @@ -155,17 +149,14 @@ function decompose(x::UFixed) end # Promotions -for T in UF +promote_rule{T<:UFixed}(::Type{T}, ::Type{Float32}) = Float32 +promote_rule{T<:UFixed}(::Type{T}, ::Type{Float64}) = Float64 +promote_rule{T<:UFixed, TR<:Rational}(::Type{T}, ::Type{TR}) = TR + +for Ti in (Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64) + Tp = eps(convert(Float32, typemax(Ti))) @eval begin - promote_rule(::Type{$T}, ::Type{Float32}) = Float32 - promote_rule(::Type{$T}, ::Type{Float64}) = Float64 - promote_rule{TR<:Rational}(::Type{$T}, ::Type{TR}) = TR - end - for Ti in (Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64) - Tp = eps(convert(Float32, typemax(Ti))) > eps(T) ? Float64 : Float32 - @eval begin - promote_rule(::Type{$T}, ::Type{$Ti}) = $Tp - end + promote_rule{T<:UFixed}(::Type{T}, ::Type{$Ti}) = $Tp > eps(T) ? Float64 : Float32 end end diff --git a/test/ufixed.jl b/test/ufixed.jl index 839e1542..14e38913 100644 --- a/test/ufixed.jl +++ b/test/ufixed.jl @@ -17,14 +17,14 @@ using FixedPointNumbers, Base.Test @test ufixed14(1.0) == 0x3fffuf14 @test ufixed12([2]) == UFixed12[0x1ffeuf12] -for T in FixedPointNumbers.UF +for T in (FixedPointNumbers.UF..., UFixed{UInt32,16}) @test zero(T) == 0 @test one(T) == 1 @test one(T) * one(T) == one(T) @test typemin(T) == 0 @test realmin(T) == 0 @test eps(zero(T)) == eps(typemax(T)) - @test sizeof(T) == 1 + (T != UFixed8) + @test sizeof(T) == sizeof(FixedPointNumbers.rawtype(T)) end @test typemax(UFixed8) == 1 @test typemax(UFixed10) == typemax(UInt16)//(2^10-1) @@ -51,7 +51,7 @@ x = UFixed8(0.5) @test convert(Float64, eps(UFixed8)) == 1/typemax(UInt8) @test convert(Float32, eps(UFixed8)) == 1.0f0/typemax(UInt8) @test convert(BigFloat, eps(UFixed8)) == BigFloat(1)/typemax(UInt8) -for T in FixedPointNumbers.UF +for T in (FixedPointNumbers.UF..., UFixed{UInt32,16}) @test convert(Bool, zero(T)) == false @test convert(Bool, one(T)) == true @test convert(Bool, convert(T, 0.2)) == true @@ -64,7 +64,7 @@ x = UFixed8(0b01010001, 0) @test ~x == UFixed8(0b10101110, 0) @test -x == 0xafuf8 -for T in FixedPointNumbers.UF +for T in (FixedPointNumbers.UF..., UFixed{UInt32,16}) x = T(0x10,0) y = T(0x25,0) fx = convert(Float32, x) @@ -113,7 +113,7 @@ function testtrunc{T}(inc::T) end end -for T in FixedPointNumbers.UF +for T in (FixedPointNumbers.UF..., UFixed{UInt32,16}) testtrunc(eps(T)) end From d97d23539fabde482198bcc865555ea8cb2d8d5f Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 13 Aug 2016 07:03:55 +0900 Subject: [PATCH 2/2] don't run 2^32 tests... --- test/ufixed.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ufixed.jl b/test/ufixed.jl index 14e38913..54aa4509 100644 --- a/test/ufixed.jl +++ b/test/ufixed.jl @@ -113,7 +113,7 @@ function testtrunc{T}(inc::T) end end -for T in (FixedPointNumbers.UF..., UFixed{UInt32,16}) +for T in FixedPointNumbers.UF testtrunc(eps(T)) end