diff --git a/Project.toml b/Project.toml index efe1227..f62358e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "StaticNumbers" uuid = "c5e4b96a-f99f-5557-8ed2-dc63ef9b5131" authors = ["Per Rutquist "] -version = "0.2.0" +version = "0.2.1" [deps] Requires = "ae029012-a4dd-5104-9daa-d747884805df" diff --git a/README.md b/README.md index d42f80f..2c0e0fd 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,10 @@ There is no `StaticRational` datatype, but a `StaticReal` with a `Rational` type parameter will convert and promote like its parameter. For example: `static(1//2) + 1 === 3//2`. +The `Unsigned` datatype currently does not work well with static numbers. +For this reason the `@stat` macro does turn unsigned numbers into static. +(This is work in progress, and subjec to change.) + `Static` numbers are only fast when fully specified. A `Vector{Static}` is much slower than a `Vector{Int}`. (A `Vector{StaticInteger{1}}` is fast and requires very little memory, diff --git a/src/StaticNumbers.jl b/src/StaticNumbers.jl index f32f94d..dbb1caa 100644 --- a/src/StaticNumbers.jl +++ b/src/StaticNumbers.jl @@ -180,11 +180,17 @@ end Base.:&(::StaticInteger{X}, ::StaticInteger{X}) where {X} = X Base.:|(::StaticInteger{X}, ::StaticInteger{X}) where {X} = X 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 +Base.:<(::ST, ::ST) where {ST<:StaticReal{X}} where {X} = false +Base.:<=(::ST, ::ST) where {ST<:StaticReal{X}} where {X} = true +# Bypass promotion in comparisons involving static unsigned integers +for fun in (:(<), :(<=)) + @eval Base.$fun(::StaticInteger{X}, y::Integer) where {X} = $fun(X, y) + @eval Base.$fun(x::Integer, ::StaticInteger{Y}) where {Y} = $fun(x, Y) + @eval Base.$fun(::StaticInteger{X}, ::StaticInteger{Y}) where {X,Y} = $fun(X, Y) +end # Three-argument function that gives no_op_err fma(x::ST, y::ST, z::ST) where {ST<:Static{X}} where {X} = fma(X,X,X) @@ -195,7 +201,7 @@ for T in (Bool, Int32, Int64, Float32, Float64, ComplexF32, ComplexF64, Irration Base.:^(x::T, ::StaticInteger{p}) where {p} = Base.literal_pow(^, x, Val(p)) end Base.:^(x::Static{X}, ::StaticInteger{p}) where {X,p} = Base.literal_pow(^, X, Val(p)) -Base.:^(x::Static{X}, ::StaticInteger{X}) where {X} = Base.literal_pow(^, X, Val(X)) #disambig +Base.:^(x::ST, ::ST) where {ST<:StaticInteger{X}} where {X} = Base.literal_pow(^, X, Val(X)) #disambig # ntuple accepts Val, so it should also accept static @inline Base.ntuple(f::F, ::StaticInteger{N}) where {F,N} = Base.ntuple(f, Val(N)) diff --git a/src/stat_macro.jl b/src/stat_macro.jl index 31107c9..b871478 100644 --- a/src/stat_macro.jl +++ b/src/stat_macro.jl @@ -13,7 +13,7 @@ functions under the macro. @inline maybe_static(f::F, args...) where {F} = f(args...) @inline function maybe_static(f::F, args::Static...) where {F} y = f(args...) - y isa Number && !(y isa Bool) ? static(y) : y + y isa Number && !(y isa Bool) && !(y isa Unsigned) ? static(y) : y end @inline maybe_static(::typeof(nfields), t) = static(nfields(t)) @@ -30,6 +30,7 @@ function calls into `trystatic`. """ statify(ex) = ex statify(x::Number) = :( static($x) ) +statify(x::Unsigned) = x statify(s::Symbol) = s == :end ? :( static($s) ) : s function statify(ex::Expr) if ex.head == :call diff --git a/test/runtests.jl b/test/runtests.jl index 3528f18..ef700fc 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -131,6 +131,9 @@ end @test widemul(static(1), true) === widemul(1, true) @test widemul(static(1.0), false) === widemul(1.0, false) + + @test isnan(static(NaN)) === true + @test isnan(static(0.0)) === false end @testset "show" begin @@ -411,6 +414,10 @@ end @test static(2:3)[2] === 3 @test static(2:3)[static(2)] === 3 @test @stat((2:3)[2]) === static(3) + + # At the moment, we don't want @stat to create static unsigned numbers. (Subject to change.) + @test UInt(1) === @stat UInt(1) + @test UInt(1) === @stat unsigned(1) end @testset "examples for doc" begin @@ -424,4 +431,14 @@ end Test.@inferred Tuple(i^2 for i in static(1):static(4)) end +# NOTE: There's still a lot of work to do on unsigned +@testset "unsigned" begin + @test static(UInt(2)) > -1 + @test UInt(2) > static(-1) + @test static(UInt(2)) > static(-1) + @test static(UInt(2)) >= -1 + @test UInt(2) >= static(-1) + @test static(UInt(2)) >= static(-1) +end + include("StaticArrays_test.jl")