Skip to content

Commit

Permalink
Bugfixes related to unsigned numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
perrutquist committed Jan 1, 2020
1 parent d1cb0e1 commit e4e4c08
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "StaticNumbers"
uuid = "c5e4b96a-f99f-5557-8ed2-dc63ef9b5131"
authors = ["Per Rutquist <[email protected]>"]
version = "0.2.0"
version = "0.2.1"

[deps]
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
12 changes: 9 additions & 3 deletions src/StaticNumbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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))
Expand Down
3 changes: 2 additions & 1 deletion src/stat_macro.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
Expand Down
17 changes: 17 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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")

2 comments on commit e4e4c08

@perrutquist
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/7413

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if Julia TagBot is installed, or can be done manually through the github interface, or via:

git tag -a v0.2.1 -m "<description of version>" e4e4c08f94663b0390117eb7d9071392869b5d1e
git push origin v0.2.1

Please sign in to comment.