diff --git a/docs/src/pages/api.md b/docs/src/pages/api.md index 68c76cb7..0e582c4e 100644 --- a/docs/src/pages/api.md +++ b/docs/src/pages/api.md @@ -60,7 +60,7 @@ same vector. We can now do this with the `Scalar` type: The size of a statically sized array is a static parameter associated with the type of the array. The `Size` trait is provided as an abstract representation of the dimensions of a static array. An array `sa::SA` of size `(dims...)` is -associated with `Size{(dims...)}()`. The following are equivalent (`@pure`) +associated with `Size{(dims...)}()`. The following are equivalent constructors: ```julia Size{(dims...,)}() diff --git a/src/SHermitianCompact.jl b/src/SHermitianCompact.jl index ab68ab21..548df21d 100644 --- a/src/SHermitianCompact.jl +++ b/src/SHermitianCompact.jl @@ -44,8 +44,8 @@ end end end -Base.@pure triangularnumber(N::Int) = div(N * (N + 1), 2) -Base.@pure triangularroot(L::Int) = div(isqrt(8 * L + 1) - 1, 2) # from quadratic formula +triangularnumber(N::Int) = div(N * (N + 1), 2) +triangularroot(L::Int) = div(isqrt(8 * L + 1) - 1, 2) # from quadratic formula lowertriangletype(::Type{SHermitianCompact{N, T, L}}) where {N, T, L} = SVector{L, T} lowertriangletype(::Type{SHermitianCompact{N, T}}) where {N, T} = SVector{triangularnumber(N), T} diff --git a/src/SOneTo.jl b/src/SOneTo.jl index cec29475..5ef3c9cd 100644 --- a/src/SOneTo.jl +++ b/src/SOneTo.jl @@ -38,7 +38,7 @@ end Base.first(::SOneTo) = 1 Base.last(::SOneTo{n}) where {n} = n::Int -@pure function Base.iterate(::SOneTo{n}) where {n} +function Base.iterate(::SOneTo{n}) where {n} if n::Int < 1 return nothing else @@ -68,7 +68,7 @@ function Base.show(io::IO, ::SOneTo{n}) where {n} print(io, "SOneTo(", n::Int, ")") end -Base.@pure function Base.checkindex(::Type{Bool}, ::SOneTo{n1}, ::SOneTo{n2}) where {n1, n2} +function Base.checkindex(::Type{Bool}, ::SOneTo{n1}, ::SOneTo{n2}) where {n1, n2} return n1::Int >= n2::Int end diff --git a/src/SUnitRange.jl b/src/SUnitRange.jl index 4661336c..32255887 100644 --- a/src/SUnitRange.jl +++ b/src/SUnitRange.jl @@ -6,7 +6,7 @@ struct SUnitRange{Start, L} <: StaticVector{L, Int} end end -@pure function check_sunitrange_params(L::Int) +function check_sunitrange_params(L::Int) if L < 0 error("Static unit range length is negative") end @@ -16,9 +16,9 @@ function check_sunitrange_params(L) throw(TypeError(:SUnitRange, "type parameters must be `Int`", Tuple{Int,}, Tuple{typeof(L),})) end -@pure SUnitRange(a::Int, b::Int) = SUnitRange{a, max(0, b - a + 1)}() +SUnitRange(a::Int, b::Int) = SUnitRange{a, max(0, b - a + 1)}() -@pure @propagate_inbounds function getindex(x::SUnitRange{Start, L}, i::Int) where {Start, L} +@propagate_inbounds function getindex(x::SUnitRange{Start, L}, i::Int) where {Start, L} @boundscheck if i < 1 || i > L throw(BoundsError(x, i)) end diff --git a/src/StaticArrays.jl b/src/StaticArrays.jl index d2b7c436..7a0e130d 100644 --- a/src/StaticArrays.jl +++ b/src/StaticArrays.jl @@ -1,6 +1,6 @@ module StaticArrays -import Base: @_propagate_inbounds_meta, @propagate_inbounds, @pure +import Base: @_propagate_inbounds_meta, @propagate_inbounds import Base: getindex, setindex!, size, similar, vec, show, length, convert, promote_op, promote_rule, map, map!, reduce, mapreduce, foldl, mapfoldl, broadcast, diff --git a/src/abstractarray.jl b/src/abstractarray.jl index 84078979..711d1e68 100644 --- a/src/abstractarray.jl +++ b/src/abstractarray.jl @@ -1,7 +1,7 @@ length(a::StaticArrayLike) = prod(Size(a))::Int length(a::Type{SA}) where {SA <: StaticArrayLike} = prod(Size(SA))::Int -@pure size(::Type{SA}) where {SA <: StaticArrayLike} = Tuple(Size(SA)) +size(::Type{SA}) where {SA <: StaticArrayLike} = Tuple(Size(SA)) @inline function size(t::Type{<:StaticArrayLike}, d::Int) S = size(t) d > length(S) ? 1 : S[d] @@ -9,7 +9,7 @@ end @inline size(a::StaticArrayLike) = Tuple(Size(a)) Base.axes(s::StaticArray) = _axes(Size(s)) -@pure function _axes(::Size{sizes}) where {sizes} +function _axes(::Size{sizes}) where {sizes} map(SOneTo, sizes) end Base.axes(rv::Adjoint{<:Any,<:StaticVector}) = (SOneTo(1), axes(rv.parent)...) @@ -86,9 +86,9 @@ sizedarray_similar_type(::Type{T},s::Size{S},::Type{Val{D}}) where {T,S,D} = Siz # Utility for computing the eltype of an array instance, type, or type # constructor. For type constructors without a definite eltype, the default # value is returned. -Base.@pure _eltype_or(a::AbstractArray, default) = eltype(a) -Base.@pure _eltype_or(::Type{<:AbstractArray{T}}, default) where {T} = T -Base.@pure _eltype_or(::Type{<:AbstractArray}, default) = default # eltype not available +_eltype_or(a::AbstractArray, default) = eltype(a) +_eltype_or(::Type{<:AbstractArray{T}}, default) where {T} = T +_eltype_or(::Type{<:AbstractArray}, default) = default # eltype not available """ _construct_similar(a, ::Size, elements::NTuple) diff --git a/src/convert.jl b/src/convert.jl index 534a3d4e..814f3ddb 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -10,15 +10,15 @@ Length(x::Args) = Length(length(x.args)) const BadArgs = Args{<:Tuple{Tuple{<:Tuple}}} # Some help functions. -@pure has_ndims(::Type{<:StaticArray{<:Tuple,<:Any,N}}) where {N} = @isdefined N -@pure has_ndims(::Type{<:StaticArray}) = false +has_ndims(::Type{<:StaticArray{<:Tuple,<:Any,N}}) where {N} = true +has_ndims(::Type{<:StaticArray}) = false if VERSION < v"1.7" - Base.ndims(::Type{<:StaticArray{<:Tuple,<:Any,N}}) where {N} = N + Base.ndims(::Type{<:StaticArray{<:Tuple,<:Any,N}}) where {N} = true end -@pure has_eltype(::Type{<:StaticArray{<:Tuple,T}}) where {T} = @isdefined T -@pure has_eltype(::Type{<:StaticArray}) = false -@pure has_size(::Type{<:StaticArray{S}}) where {S<:Tuple} = @isdefined S -@pure has_size(::Type{<:StaticArray}) = false +has_eltype(::Type{<:StaticArray{<:Tuple,T}}) where {T} = true +has_eltype(::Type{<:StaticArray}) = false +has_size(::Type{<:StaticArray{S}}) where {S<:Tuple} = true +has_size(::Type{<:StaticArray}) = false # workaround for https://github.com/JuliaArrays/StaticArrays.jl/issues/1047 has_size(::Type{SVector}) = false has_size(::Type{MVector}) = false @@ -27,11 +27,11 @@ has_size(::Type{MMatrix}) = false has_size(::Type{SMatrix{N}}) where {N} = false has_size(::Type{MMatrix{N}}) where {N} = false -@pure has_size1(::Type{<:StaticMatrix{M}}) where {M} = @isdefined M -@pure has_size1(::Type{<:StaticMatrix}) = false +has_size1(::Type{<:StaticMatrix{M}}) where {M} = true +has_size1(::Type{<:StaticMatrix}) = false _size1(::Type{<:StaticMatrix{M}}) where {M} = M @generated function _sqrt(::Length{L}) where {L} - N = round(Int, sqrt(L)) + N = isqrt(L) N^2 == L && return :($N) throw(DimensionMismatch("Input's length must be perfect square")) end @@ -40,15 +40,15 @@ end SA′ = construct_type(::Type{SA}, x) where {SA<:StaticArray} Pick a proper constructor `SA′` based on `x` if `SA(x)`/`SA(x...)` has no specific definition. -The default returned `SA′` is `SA` itself for user defined `StaticArray`s. This differs from +The default returned `SA′` is `SA` itself for user defined `StaticArray`s. This differs from `similar_type()` in that `SA′` should always be a subtype of `SA`. !!! note - To distinguish `SA(x...)` and `SA(x::Tuple)`, the former calls + To distinguish `SA(x...)` and `SA(x::Tuple)`, the former calls `construct_type(SA, StaticArrays.Args(x))` instead of `construct_type(SA, x)`. !!! note - Please make sure `SA'(x)` has a specific definition if the default behavior is overloaded. + Please make sure `SA'(x)` has a specific definition if the default behavior is overloaded. Otherwise construction might fall into infinite recursion. --- @@ -66,7 +66,7 @@ The adaption rules for offical `StaticArray`s could be summarized as: If `SA` is not fully static-sized, then we always try to fill `SA` with `x`'s elements, and the constructor's `Size` is derived based on: - 1. If `SA <: StaticVector`, then we use `length(x)` as the output `Length` + 1. If `SA <: StaticVector`, then we use `length(x)` as the output `Length` 2. If `SA <: StaticMatrix{M}`, then we use `(M, N)` (`N = length(x) ÷ M`) as the output `Size` 3. If `SA <: StaticMatrix{M,M} where M`, then we use `(N, N)` (`N = sqrt(length(x)`) as the output `Size`. - SA(x...) @@ -215,4 +215,4 @@ end # `float` and `real` of StaticArray types, analogously to application to scalars (issue 935) float(::Type{SA}) where SA<:StaticArray{_S,T,_N} where {_S,T,_N} = similar_type(SA, float(T)) -real(::Type{SA}) where SA<:StaticArray{_S,T,_N} where {_S,T,_N} = similar_type(SA, real(T)) \ No newline at end of file +real(::Type{SA}) where SA<:StaticArray{_S,T,_N} where {_S,T,_N} = similar_type(SA, real(T)) diff --git a/src/indexing.jl b/src/indexing.jl index c73bfc0d..3c845940 100644 --- a/src/indexing.jl +++ b/src/indexing.jl @@ -71,7 +71,7 @@ end ## Indexing utilities ## ######################### -@pure unpack_size(::Type{Size{S}}) where {S} = map(Size, S) +unpack_size(::Type{Size{S}}) where {S} = map(Size, S) @inline index_size(::Size, ::Int) = Size() @inline index_size(::Size, a::StaticArray) = Size(a) diff --git a/src/initializers.jl b/src/initializers.jl index edbae358..23e8ca4c 100644 --- a/src/initializers.jl +++ b/src/initializers.jl @@ -37,11 +37,9 @@ const SA_F64 = SA{Float64} @inline Base.typed_hcat(sa::Type{SA}, xs::Number...) = similar_type(sa, Size(1,length(xs)))(xs) @inline Base.typed_hcat(sa::Type{SA{T}}, xs::Number...) where T = similar_type(sa, Size(1,length(xs)))(xs) -Base.@pure function _SA_hvcat_transposed_size(rows) +function _SA_hvcat_transposed_size(rows) M = rows[1] if any(r->r != M, rows) - # @pure may not throw... probably. See - # https://discourse.julialang.org/t/can-pure-functions-throw-an-error/18459 return nothing end Size(M, length(rows)) @@ -65,7 +63,7 @@ if VERSION >= v"1.7" args = (:(x[$i]) for i in a) return :(tuple($(args...))) end - + @inline function _SA_typed_hvncat(sa, dimsshape, row_first, xs) msize = Size(dimsshape) xs′ = row_first ? reorder(xs, Val(msize[1]), Val(msize[2])) : xs diff --git a/src/traits.jl b/src/traits.jl index 94054140..14118b9b 100644 --- a/src/traits.jl +++ b/src/traits.jl @@ -33,34 +33,32 @@ Base.show(io::IO, ::Length{L}) where {L} = print(io, "Length(", L, ")") Length(a::AbstractArray) = Length(Size(a)) Length(::Type{A}) where {A <: AbstractArray} = Length(Size(A)) -@pure Length(L::Int) = Length{L}() +Length(L::Int) = Length{L}() Length(::Size{S}) where {S} = _Length(S...) -@pure _Length(S::Int...) = Length{prod(S)}() +_Length(S::Int...) = Length{prod(S)}() @inline _Length(S...) = Length{Dynamic()}() -# Some @pure convenience functions for `Size` -@pure (::Type{Tuple})(::Size{S}) where {S} = S +(::Type{Tuple})(::Size{S}) where {S} = S -@pure getindex(::Size{S}, i::Int) where {S} = i <= length(S) ? S[i] : 1 +getindex(::Size{S}, i::Int) where {S} = i <= length(S) ? S[i] : 1 -@pure length(::Size{S}) where {S} = length(S) -@pure length_val(::Size{S}) where {S} = Val{length(S)} +length(::Size{S}) where {S} = length(S) +length_val(::Size{S}) where {S} = Val{length(S)} # Note - using === here, as Base doesn't inline == for tuples as of julia-0.6 -@pure Base.:(==)(::Size{S}, s::Tuple{Vararg{Int}}) where {S} = S === s -@pure Base.:(==)(s::Tuple{Vararg{Int}}, ::Size{S}) where {S} = s === S +Base.:(==)(::Size{S}, s::Tuple{Vararg{Int}}) where {S} = S === s +Base.:(==)(s::Tuple{Vararg{Int}}, ::Size{S}) where {S} = s === S -@pure Base.prod(::Size{S}) where {S} = prod(S) +Base.prod(::Size{S}) where {S} = prod(S) Base.LinearIndices(::Size{S}) where {S} = LinearIndices(S) -@pure size_tuple(::Size{S}) where {S} = Tuple{S...} +size_tuple(::Size{S}) where {S} = Tuple{S...} -# Some @pure convenience functions for `Length` -@pure (::Type{Int})(::Length{L}) where {L} = L +(::Type{Int})(::Length{L}) where {L} = L -@pure Base.:(==)(::Length{L}, l::Int) where {L} = L == l -@pure Base.:(==)(l::Int, ::Length{L}) where {L} = l == L +Base.:(==)(::Length{L}, l::Int) where {L} = L == l +Base.:(==)(l::Int, ::Length{L}) where {L} = l == L # unroll_tuple also works with `Length` @propagate_inbounds unroll_tuple(f, ::Length{L}) where {L} = unroll_tuple(f, Val{L}) @@ -72,7 +70,7 @@ Base.LinearIndices(::Size{S}) where {S} = LinearIndices(S) Determine whether two sizes match, in the sense that they have the same number of dimensions, and their dimensions match as determined by [`dimmatch`](@ref). """ -@pure sizematch(::Size{S1}, ::Size{S2}) where {S1, S2} = sizematch(S1, S2) +sizematch(::Size{S1}, ::Size{S2}) where {S1, S2} = sizematch(S1, S2) @inline sizematch(::Tuple{}, ::Tuple{}) = true @inline sizematch(S1::Tuple{Vararg{StaticDimension, N}}, S2::Tuple{Vararg{StaticDimension, N}}) where {N} = dimmatch(S1[1], S2[1]) && sizematch(Base.tail(S1), Base.tail(S2)) @@ -115,4 +113,4 @@ end # Return the "diagonal size" of a matrix - the minimum of the two dimensions diagsize(A::StaticMatrix) = diagsize(Size(A)) -@pure diagsize(::Size{S}) where {S} = min(S...) +diagsize(::Size{S}) where {S} = min(S...)