From d1cb0e1f457b7e2e2641cfd5727deed2b6d93142 Mon Sep 17 00:00:00 2001 From: Per Rutquist Date: Wed, 1 Jan 2020 19:44:49 +0100 Subject: [PATCH] cleanup --- Project.toml | 2 +- src/StaticNumbers.jl | 48 ++++++++++++++++++-------------------------- test/runtests.jl | 9 +++++++++ 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/Project.toml b/Project.toml index 1bcb038..efe1227 100644 --- a/Project.toml +++ b/Project.toml @@ -7,8 +7,8 @@ version = "0.2.0" Requires = "ae029012-a4dd-5104-9daa-d747884805df" [compat] -julia = "0.7, 1" Requires = "1.0, 1" +julia = "0.7, 1" [extras] StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" diff --git a/src/StaticNumbers.jl b/src/StaticNumbers.jl index d9bf53a..f32f94d 100644 --- a/src/StaticNumbers.jl +++ b/src/StaticNumbers.jl @@ -84,36 +84,24 @@ Base.@pure Base.Val(::Static{X}) where X = Val(X) const StaticOrInt = Union{StaticInteger, Int} # Promotion -Base.promote_rule(::Type{<:Static{X}}, ::Type{<:Static{X}}) where {X} = - typeof(X) -Base.promote_rule(::Type{<:AbstractIrrational}, ::Type{<:Static{X}}) where {X} = - promote_type(Float64, typeof(X)) +# We need to override promote and promote_typeof because they don't even call +# promote_rule for all-same types. +Base.promote(::ST, ys::ST...) where {ST <: Static{X}} where {X} = ntuple(i->X, 1+length(ys)) +Base.promote_type(::Type{ST}, ::Type{ST}) where {ST <: Static{X}} where {X} = typeof(X) +Base.promote_typeof(::ST, ::ST...) where {ST <: Static{X}} where {X} = typeof(X) + +# To avoid infinite recursion, we need this: +Base.promote_type(::Type{<:Static{X}}, T::Type...) where {X} = promote_type(typeof(X), promote_type(T...)) # Loop over all three types specifically, instead of dispatching on the Union. for ST in (StaticInteger, StaticReal, StaticNumber) - # We need to override promote and promote_typeof because they don't even call - # promote_rule for all-same types. - Base.promote(::ST{X}, ys::ST{X}...) where {X} = ntuple(i->X, 1+length(ys)) - Base.promote_type(::Type{ST{X}}, ::Type{ST{X}}) where {X} = typeof(X) - Base.promote_typeof(::ST{X}, ::ST{X}...) where {X} = typeof(X) - # To avoid infinite recursion, we need this: - Base.promote_type(::Type{ST{X}}, T::Type...) where {X} = promote_type(typeof(X), promote_type(T...)) - - Base.promote_rule(::Type{<:ST{X}}, ::Type{T}) where {X,T<:Number} = promote_type(typeof(X), T) + Base.promote_rule(::Type{ST{X}}, ::Type{T}) where {X,T<:Number} = promote_type(typeof(X), T) # Constructors (::Type{Complex{T}})(::ST{X}) where {T<:Real, X} = Complex{T}(X) (::Type{Rational{T}})(::ST{X}) where {T<:Integer, X} = Rational{T}(X) end -Base.promote_rule(::Type{<:Static{X}}, ::Type{<:Static{Y}}) where {X,Y} = - promote_type(typeof(X),typeof(Y)) - -# Bool has a special rule that we need to override? -#Base.promote_rule(::Type{Bool}, ::Type{StaticInteger{X}}) where {X} = promote_type(Bool, typeof(X)) - -#Base.BigInt(::Static{X}) where {X} = BigInt(X) - "ofstatictype(x,y) - like oftype(x,y), but return a `Static` `x` is a `Static`." ofstatictype(::Static{X}, y) where {X} = static(oftype(X, y)) ofstatictype(x, y) = oftype(x, y) @@ -137,7 +125,7 @@ end for fun in (:-, :zero, :one, :oneunit, :trailing_zeros, :widen, :decompose) @eval Base.$fun(::Static{X}) where X = Base.$fun(X) end -for fun in (:trunc, :floor, :ceil, :round) +for fun in (:trunc, :floor, :ceil, :round, :isnan) @eval Base.$fun(::Union{StaticReal{X}, StaticNumber{X}}) where {X} = Base.$fun(X) end for fun in (:zero, :one, :oneunit) @@ -187,17 +175,19 @@ for f in (:+, :-, :*, :/, :^) @eval Base.$f(::Static{X}, ::Static{X}) where {X} = $f(X,X) end # ...where simplifications are possible: +# Note: We allow creation of specific static numbers, like 1 and 0 (as an exception) +# since this cannot lead to the set of static numbers growing uncontrollably. Base.:&(::StaticInteger{X}, ::StaticInteger{X}) where {X} = X Base.:|(::StaticInteger{X}, ::StaticInteger{X}) where {X} = X -Base.xor(::StaticInteger{X}, ::StaticInteger{X}) where {X} = zero(X) -Base.:<(::Static{X}, ::Static{X}) where {X} = false -Base.:<=(::Static{X}, ::Static{X}) where {X} = true -Base.rem(::Static{X}, ::Static{X}) where {X} = (X==0 || isinf(X)) ? X isa AbstractFloat ? oftype(X, NaN) : throw(DivideError()) : zero(X) -Base.mod(::Static{X}, ::Static{X}) where {X} = (X==0 || isinf(X)) ? X isa AbstractFloat ? oftype(X, NaN) : throw(DivideError()) : zero(X) -Base.div(::Static{X}, ::Static{X}) where {X} = static(one(X)) # Needed for Julia > 1.3 +Base.xor(::StaticInteger{X}, ::StaticInteger{X}) where {X} = static(zero(X)) +Base.:<(::ST, ::ST) where {ST<:Static{X}} where {X} = false +Base.:<=(::ST, ::ST) where {ST<:Static{X}} where {X} = true +Base.rem(::ST, ::ST) where {ST<:Static{X}} where {X} = (X==0 || isinf(X)) ? X isa AbstractFloat ? static(oftype(X, NaN)) : throw(DivideError()) : static(zero(X)) +Base.mod(::ST, ::ST) where {ST<:Static{X}} where {X} = (X==0 || isinf(X)) ? X isa AbstractFloat ? static(oftype(X, NaN)) : throw(DivideError()) : static(zero(X)) +Base.div(::ST, ::ST) where {ST<:Static{X}} where {X} = static(one(X)) # Needed for Julia > 1.3 # Three-argument function that gives no_op_err -fma(x::Static{X}, y::Static{X}, z::Static{X}) where {X} = fma(X,X,X) +fma(x::ST, y::ST, z::ST) where {ST<:Static{X}} where {X} = fma(X,X,X) # Static powers using Base.literal_pow. # This avoids DomainError in some cases? diff --git a/test/runtests.jl b/test/runtests.jl index 65cc290..3528f18 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,6 +14,8 @@ using Test @test zero(static(1)) === 0 @test zero(static(1.0)) === 0.0 + @test zero(typeof(static(1))) === 0 + @test zero(typeof(static(1.0))) === 0.0 @test static(true) == true @test static(false) == false @@ -122,6 +124,13 @@ end @test Base.promote_typeof(static(1), static(1)) === Int @test static(1):static(2):5 isa LengthStepRange{Int64,StaticInteger{-1},StaticInteger{2},Int64} + + @test Rational{Int}(static(3//2)) === 3//2 + + @test Base.promote_rule(StaticInteger{3}, StaticReal{3.14}) === Float64 + + @test widemul(static(1), true) === widemul(1, true) + @test widemul(static(1.0), false) === widemul(1.0, false) end @testset "show" begin