diff --git a/src/FixedPointNumbers.jl b/src/FixedPointNumbers.jl index fd0abb95..a5b0848d 100644 --- a/src/FixedPointNumbers.jl +++ b/src/FixedPointNumbers.jl @@ -4,7 +4,7 @@ import Base: ==, <, <=, -, +, *, /, ~, isapprox, convert, promote_rule, show, isinteger, abs, decompose, isnan, isinf, isfinite, zero, oneunit, one, typemin, typemax, floatmin, floatmax, eps, reinterpret, - float, trunc, round, floor, ceil, bswap, + big, rationalize, float, trunc, round, floor, ceil, bswap, div, fld, rem, mod, mod1, fld1, min, max, minmax, rand, length @@ -71,6 +71,14 @@ function (::Type{Ti})(x::FixedPoint) where {Ti <: Integer} end Base.Rational{Ti}(x::FixedPoint) where {Ti <: Integer} = Rational{Ti}(Rational(x)) +big(::Type{<:FixedPoint}) = BigFloat +big(x::FixedPoint) = convert(BigFloat, x) + +rationalize(x::FixedPoint; tol::Real=eps(x)) = rationalize(Int, x, tol=tol) +function rationalize(::Type{Ti}, x::FixedPoint; tol::Real=eps(x)) where Ti <: Integer + tol <= eps(x) ? Rational{Ti}(x) : rationalize(Ti, float(x), tol) +end + """ isapprox(x::FixedPoint, y::FixedPoint; rtol=0, atol=max(eps(x), eps(y))) diff --git a/src/normed.jl b/src/normed.jl index 0593567a..b34ae065 100644 --- a/src/normed.jl +++ b/src/normed.jl @@ -244,7 +244,7 @@ function Base.Float64(x::Normed{UInt128,f}) where f end end -Base.BigFloat(x::Normed) = reinterpret(x)*(1/BigFloat(rawone(x))) +Base.BigFloat(x::Normed) = reinterpret(x) / BigFloat(rawone(x)) Base.Rational(x::Normed) = reinterpret(x)//rawone(x) diff --git a/test/fixed.jl b/test/fixed.jl index 2657ff08..7285b061 100644 --- a/test/fixed.jl +++ b/test/fixed.jl @@ -253,14 +253,6 @@ end @test varm(a, m) === varm(af, m) end -@testset "convert result type" begin - x = Fixed{Int8,7}(0.75) - for T in (Float16, Float32, Float64, BigFloat) - y = convert(T, x) - @test isa(y, T) - end -end - @testset "bool conversions" begin @test convert(Bool, 0.0Q1f6) === false @test convert(Bool, 1.0Q1f6) === true @@ -269,7 +261,7 @@ end @test_broken convert(Bool, Fixed{Int8,8}(0.2)) # TODO: remove this end -@testset "Integer conversions" begin +@testset "integer conversions" begin @test convert(Int, Q1f6(1)) === 1 @test convert(Integer, Q1f6(1)) === Int8(1) @test convert(UInt, 1Q1f6) === UInt(1) @@ -280,7 +272,19 @@ end @testset "rational conversions" begin @test convert(Rational, -0.75Q1f6) === Rational{Int8}(-3//4) @test convert(Rational, -0.75Q0f7) === Rational{Int16}(-3//4) - @test convert(Rational{Int}, -0.75Q0f7) === Rational(-3//4) + @test convert(Rational{Int}, -0.75Q0f7) === Rational{Int}(-3//4) + + @test rationalize(-0.75Q3f4) === Rational{Int}(-3//4) + @test rationalize(Int16, 0.81Q3f4) === Rational{Int16}(13//16) + @test rationalize(-0.81Q3f4, tol=0.02) === Rational{Int}(-13//16) + @test rationalize(Int8, -0.81Q3f4, tol=0.07) === Rational{Int8}(-3//4) +end + +@testset "BigFloat conversions" begin + @test convert(BigFloat, -0.75Q0f7)::BigFloat == big"-0.75" + + @test big(Q7f0) === BigFloat # !== BigInt + @test big(0.75Q3f4)::BigFloat == big"0.75" end @testset "Floating-point conversions" begin @@ -290,7 +294,7 @@ end end @testset "conversions to float" begin - for T in (Float16, Float32, Float64, BigFloat) + for T in (Float16, Float32, Float64) @test isa(convert(T, Q0f7(0.3)), T) end diff --git a/test/normed.jl b/test/normed.jl index 44b8f33e..dd101b8e 100644 --- a/test/normed.jl +++ b/test/normed.jl @@ -110,7 +110,6 @@ end @test convert(Integer, one(T)) == 1 @test convert(Rational, one(T)) == 1 end - @test convert(Rational, convert(N0f8, 0.5)) == 0x80//0xff @test convert(N0f16, one(N0f8)) === one(N0f16) @test convert(N0f16, N0f8(0.5)).i === 0x8080 @test convert(Normed{UInt16,7}, Normed{UInt8,7}(0.504)) === Normed{UInt16,7}(0.504) @@ -124,6 +123,24 @@ end @test_throws InexactError convert(Int8, 256N8f8) end +@testset "rational conversions" begin + @test convert(Rational, 0.5N0f8) === Rational{UInt8}(0x80//0xff) + @test convert(Rational, 0.5N4f12) === Rational{UInt16}(0x800//0xfff) + @test convert(Rational{Int}, 0.5N0f8) === Rational{Int}(0x80//0xff) + + @test rationalize(0.8N0f8) === Rational{Int}(4//5) + @test rationalize(Int16, 0.804N0f8) === Rational{Int16}(41//51) + @test rationalize(0.804N0f8, tol=0.002) === Rational{Int}(41//51) + @test rationalize(Int8, 0.804N0f8, tol=0.005) === Rational{Int8}(4//5) +end + +@testset "BigFloat conversions" begin + @test convert(BigFloat, 0.5N0f8)::BigFloat == 128 / big"255" + + @test big(N7f1) === BigFloat # !== BigInt + @test big(0.5N4f4)::BigFloat == 8 / big"15" +end + @testset "conversion from float" begin # issue 102 for T in (UInt8, UInt16, UInt32, UInt64, UInt128) @@ -158,7 +175,7 @@ end @testset "conversions to float" begin x = N0f8(0.3) - for T in (Float16, Float32, Float64, BigFloat) + for T in (Float16, Float32, Float64) y = convert(T, x) @test isa(y, T) end