-
Notifications
You must be signed in to change notification settings - Fork 37
/
static.jl
70 lines (58 loc) · 2.77 KB
/
static.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
"""
A statically sized `Int`.
Use `Static(N)` instead of `Val(N)` when you want it to behave like a number.
"""
struct Static{N} <: Integer
Static{N}() where {N} = new{N::Int}()
end
Base.@pure Static(N::Int) = Static{N}()
Static(N) = Static(convert(Int,N))
Static(::Val{N}) where {N} = Static{N}()
@inline Base.Val(::Static{N}) where {N} = Val{N}()
Base.convert(::Type{T}, ::Static{N}) where {T<:Number,N} = convert(T, N)
Base.convert(::Type{Static{N}}, ::Static{N}) where {N} = Static{N}()
Base.promote_rule(::Type{<:Static}, ::Type{T}) where {T} = promote_rule(Int, T)
Base.promote_rule(::Type{T}, ::Type{<:Static}) where {T} = promote_rule(T, Int)
Base.promote_rule(::Type{<:Static}, ::Type{<:Static}) where {T} = Int
Base.:(%)(::Static{N}, ::Type{Integer}) where {N} = N
_get(::Static{N}) where {N} = N
_get(::Type{Static{N}}) where {N} = N
@inline Base.iszero(::Static{0}) = true
@inline Base.iszero(::Static) = false
Base.:(+)(i::Number, ::Static{0}) = i
Base.:(+)(::Static{0}, i::Number) = i
Base.:(+)(::Static{0}, ::Static{0}) = Static{0}()
Base.:(+)(::Static{M}, ::Static{N}) where {M,N} = Static{M + N}()
Base.:(-)(::Static{0}, i::Number) = -i
Base.:(-)(i::Number, ::Static{0}) = i
Base.:(-)(::Static{0}, ::Static{0}) = Static{0}()
Base.:(-)(::Static{M}, ::Static{N}) where {M,N} = Static{M - N}()
Base.:(*)(::Static{0}, i::Number) = Static{0}()
Base.:(*)(i::Number, ::Static{0}) = Static{0}()
Base.:(*)(::Static{0}, ::Static{0}) = Static{0}()
Base.:(*)(::Static{1}, i::Number) = i
Base.:(*)(i::Number, ::Static{1}) = i
Base.:(*)(::Static{1}, ::Static{1}) = Static{1}()
Base.:(*)(::Static{M}, ::Static{N}) where {M,N} = Static{M * N}()
Base.:(÷)(::Static{M}, ::Static{N}) where {M,N} = Static{M ÷ N}()
Base.:(%)(::Static{M}, ::Static{N}) where {M,N} = Static{M % N}()
Base.:(<<)(::Static{M}, ::Static{N}) where {M,N} = Static{M << N}()
Base.:(>>)(::Static{M}, ::Static{N}) where {M,N} = Static{M >> N}()
Base.:(>>>)(::Static{M}, ::Static{N}) where {M,N} = Static{M >>> N}()
Base.:(&)(::Static{M}, ::Static{N}) where {M,N} = Static{M & N}()
Base.:(|)(::Static{M}, ::Static{N}) where {M,N} = Static{M | N}()
Base.:(⊻)(::Static{M}, ::Static{N}) where {M,N} = Static{M ⊻ N}()
Base.:(:)(L, ::Static{U}) where {U} = OptionallyStaticUnitRange(L, Val(U))
Base.:(:)(::Static{L}, U) where {L} = OptionallyStaticUnitRange(Val(L), U)
Base.:(:)(::Static{L}, ::Static{U}) where {L,U} = OptionallyStaticUnitRange(Val(L), Val(U))
Base.:(==)(::Static{M}, ::Static{N}) where {M,N} = false
Base.:(==)(::Static{M}, ::Static{M}) where {M} = true
"""
ntuple(f::F, ::Static{N}) -> Tuple{Vararg{Any,N}}
Fully unrolled evaluation of `1:N`.
"""
@generated function Base.ntuple(f::F, ::Static{N}) where {F,N}
t = Expr(:tuple)
foreach(n -> push!(t.args, Expr(:call, :f, n)), 1:N)
Expr(:block, Expr(:meta, :inline), t)
end