diff --git a/.gitignore b/.gitignore index 42f07ea..b6f8b8d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.jl.cov *.jl.mem +Manifest.toml diff --git a/Project.toml b/Project.toml index c54e986..a6141ac 100644 --- a/Project.toml +++ b/Project.toml @@ -3,11 +3,15 @@ uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439" authors = ["Tim Holy "] version = "0.4.0" +[deps] +Requires = "ae029012-a4dd-5104-9daa-d747884805df" + [compat] julia = "0.7, 1" [extras] +FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test"] +test = ["FixedPointNumbers", "Test"] diff --git a/src/Ratios.jl b/src/Ratios.jl index 301a6fa..c7a4a98 100644 --- a/src/Ratios.jl +++ b/src/Ratios.jl @@ -2,6 +2,8 @@ module Ratios import Base: convert, promote_rule, *, /, +, -, ^, ==, decompose +using Requires + export SimpleRatio struct SimpleRatio{T<:Integer} <: Real @@ -9,14 +11,16 @@ struct SimpleRatio{T<:Integer} <: Real den::T end +SimpleRatio(num::Integer, den::Integer) = SimpleRatio(promote(num, den)...) + convert(::Type{BigFloat}, r::SimpleRatio{S}) where {S} = BigFloat(r.num)/r.den function convert(::Type{T}, r::SimpleRatio{S}) where {T<:AbstractFloat,S} P = promote_type(T,S) convert(T, convert(P, r.num)/convert(P, r.den)) end -convert(::Type{SimpleRatio{T}}, i::Integer) where {T<:Integer} = SimpleRatio{T}(convert(T, i), one(T)) -convert(::Type{SimpleRatio{T}}, r::Rational{S}) where {T<:Integer, S<:Integer} = SimpleRatio(convert(T, r.num), convert(T, r.den)) -convert(::Type{Rational{T}}, r::SimpleRatio{S}) where {T<:Integer, S<:Integer} = convert(T, r.num) // convert(T, r.den) +SimpleRatio{T}(i::Integer) where {T<:Integer} = SimpleRatio{T}(convert(T, i), oneunit(T)) +SimpleRatio{T}(r::Rational{S}) where {T<:Integer, S<:Integer} = SimpleRatio(convert(T, r.num), convert(T, r.den)) +Rational{T}(r::SimpleRatio{S}) where {T<:Integer, S<:Integer} = convert(T, r.num) // convert(T, r.den) *(x::SimpleRatio, y::SimpleRatio) = SimpleRatio(x.num*y.num, x.den*y.den) *(x::SimpleRatio, y::Bool) = SimpleRatio(x.num*y, x.den) @@ -57,4 +61,17 @@ end decompose(x::SimpleRatio) = x.num, 0, x.den +function __init__() + @require FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" begin + using .FixedPointNumbers: FixedPoint, Fixed, Normed, rawone + rawone_noerr(::Type{Fixed{T,f}}) where {T,f} = widen(oneunit(T)) << f + rawone_noerr(::Type{N}) where N<:Normed = rawone(N) + rawone_noerr(x::FixedPoint) = rawone_noerr(typeof(x)) + Base.promote_rule(::Type{SimpleRatio{S}}, ::Type{<:FixedPoint{T}}) where {S<:Integer,T<:Integer} = SimpleRatio{promote_type(S, T)} + SimpleRatio{S}(x::FixedPoint) where S<:Integer = SimpleRatio{S}(reinterpret(x), rawone_noerr(x)) + SimpleRatio(x::FixedPoint) = SimpleRatio(reinterpret(x), rawone_noerr(x)) + Base.convert(::Type{S}, x::FixedPoint) where S<:SimpleRatio = S(x) + end +end + end diff --git a/test/runtests.jl b/test/runtests.jl index d229487..f219f64 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,36 +1,45 @@ using Ratios, Test +using FixedPointNumbers -r = SimpleRatio(1,2) -@test convert(Float64, r) == 0.5 -@test convert(Float32, r) == 0.5f0 -@test convert(BigFloat, r) == BigFloat(1)/2 +@testset "SimpleRatio" begin + r = SimpleRatio(1,2) + @test convert(Float64, r) == 0.5 + @test convert(Float32, r) == 0.5f0 + @test convert(BigFloat, r) == BigFloat(1)/2 -r2 = SimpleRatio(2,3) -@test r*r2 == SimpleRatio(2,6) == SimpleRatio(1,3) -@test r2*3 == 3*r2 == 2 -@test r*false == false*r == 0 -@test r/r2 == SimpleRatio(3,4) -@test r/2 == SimpleRatio(1,4) -@test 2/r == 4 -@test 4 == 2/r -@test r+1 == 1+r == SimpleRatio(3,2) -@test r-1 == SimpleRatio(-1,2) -@test 1-r == r -@test r+r2 == SimpleRatio(7,6) -@test r-r2 == SimpleRatio(-1,6) -@test r^2 == SimpleRatio(1,4) -@test -r == SimpleRatio(-1,2) -@test 0.2*r ≈ 0.1 -@test r == 0.5 -@test 0.5 == r + r2 = SimpleRatio(2,3) + @test r*r2 == SimpleRatio(2,6) == SimpleRatio(1,3) + @test r2*3 == 3*r2 == 2 + @test r*false == false*r == 0 + @test r/r2 == SimpleRatio(3,4) + @test r/2 == SimpleRatio(1,4) + @test 2/r == 4 + @test 4 == 2/r + @test r+1 == 1+r == SimpleRatio(3,2) + @test r-1 == SimpleRatio(-1,2) + @test 1-r == r + @test r+r2 == SimpleRatio(7,6) + @test r-r2 == SimpleRatio(-1,6) + @test r^2 == SimpleRatio(1,4) + @test -r == SimpleRatio(-1,2) + @test 0.2*r ≈ 0.1 + @test r == 0.5 + @test 0.5 == r -@test_throws OverflowError -SimpleRatio(0x02,0x03) + @test_throws OverflowError -SimpleRatio(0x02,0x03) -@test r + SimpleRatio(0x02,0x03) == SimpleRatio(7,6) + @test r + SimpleRatio(0x02,0x03) == SimpleRatio(7,6) -@test SimpleRatio(11, 10) == 11//10 -@test 1//3 + SimpleRatio(1, 5) == 8//15 + @test SimpleRatio(11, 10) == 11//10 + @test 1//3 + SimpleRatio(1, 5) == 8//15 -@test isfinite(SimpleRatio(0,0)) == false -@test isfinite(SimpleRatio(1,0)) == false -@test isfinite(SimpleRatio(2,1)) == true + @test isfinite(SimpleRatio(0,0)) == false + @test isfinite(SimpleRatio(1,0)) == false + @test isfinite(SimpleRatio(2,1)) == true + + @test SimpleRatio(5,3) * 0.035N0f8 == SimpleRatio{Int}(rationalize((5*0.035N0f8)/3)) + @test SimpleRatio(5,3) * 0.035N4f12 == SimpleRatio{Int}(rationalize((5*0.035N4f12)/3)) + @test SimpleRatio(5,3) * -0.03Q0f7 == SimpleRatio{Int}(rationalize((5.0*(-0.03Q0f7))/3)) + r = @inferred(SimpleRatio(0.75Q0f7)) + @test r == 3//4 && r isa SimpleRatio{Int16} +end