Skip to content

Commit db98a1a

Browse files
authored
Merge pull request #534 from JuliaArrays/ajf/SOneTo
Add `SOneTo` as `AbstractUnitRange` to represent `axes(::StaticArray)`
2 parents 9368cba + dc00652 commit db98a1a

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

src/SOneTo.jl

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""
2+
SOneTo(n)
3+
4+
Return a statically-sized `AbstractUnitRange` starting at `1`, functioning as the `axes` of
5+
a `StaticArray`.
6+
"""
7+
struct SOneTo{n} <: AbstractUnitRange{Int}
8+
end
9+
10+
SOneTo(n::Int) = SOneTo{n}()
11+
12+
Base.axes(s::SOneTo) = (s,)
13+
Base.size(s::SOneTo) = (length(s),)
14+
Base.length(s::SOneTo{n}) where {n} = n
15+
16+
function Base.getindex(s::SOneTo, i::Int)
17+
@boundscheck checkbounds(s, i)
18+
return i
19+
end
20+
function Base.getindex(s::SOneTo, s2::SOneTo)
21+
@boundscheck checkbounds(s, s2)
22+
return s2
23+
end
24+
25+
Base.first(::SOneTo) = 1
26+
Base.last(::SOneTo{n}) where {n} = n::Int
27+
28+
@pure function Base.iterate(::SOneTo{n}) where {n}
29+
if n::Int < 1
30+
return nothing
31+
else
32+
(1, 1)
33+
end
34+
end
35+
function Base.iterate(::SOneTo{n}, s::Int) where {n}
36+
if s < n::Int
37+
s2 = s + 1
38+
return (s2, s2)
39+
else
40+
return nothing
41+
end
42+
end
43+
44+
function Base.getproperty(::SOneTo{n}, s::Symbol) where {n}
45+
if s === :start
46+
return 1
47+
elseif s === :stop
48+
return n::Int
49+
else
50+
error("type SOneTo has no property $s")
51+
end
52+
end
53+
54+
function Base.show(io::IO, ::SOneTo{n}) where {n}
55+
print(io, "SOneTo(", n::Int, ")")
56+
end
57+
58+
Base.@pure function Base.checkindex(::Type{Bool}, ::SOneTo{n1}, ::SOneTo{n2}) where {n1, n2}
59+
return n1::Int >= n2::Int
60+
end

src/StaticArrays.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import LinearAlgebra: transpose, adjoint, dot, eigvals, eigen, lyap, tr,
2525
import LinearAlgebra: eye
2626
end
2727

28+
export SOneTo
2829
export StaticScalar, StaticArray, StaticVector, StaticMatrix
2930
export Scalar, SArray, SVector, SMatrix
3031
export MArray, MVector, MMatrix
@@ -40,6 +41,8 @@ export @MVector, @MMatrix, @MArray
4041
export similar_type
4142
export push, pop, pushfirst, popfirst, insert, deleteat, setindex
4243

44+
include("SOneTo.jl")
45+
4346
"""
4447
abstract type StaticArray{S, T, N} <: AbstractArray{T, N} end
4548
StaticScalar{T} = StaticArray{Tuple{}, T, 0}

src/abstractarray.jl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ end
99
@inline size(a::StaticArray) = size(typeof(a))
1010
@inline size(a::StaticArray, d::Int) = size(typeof(a), d)
1111

12+
Base.axes(s::StaticArray) = _axes(Size(s))
13+
@pure function _axes(::Size{sizes}) where {sizes}
14+
map(SOneTo, sizes)
15+
end
16+
17+
function Base.summary(io::IO, a, inds::Tuple{SOneTo, Vararg{SOneTo}})
18+
print(io, Base.dims2string(length.(inds)), " ")
19+
Base.showarg(io, a, true)
20+
end
21+
1222
# This seems to confuse Julia a bit in certain circumstances (specifically for trailing 1's)
1323
@inline function Base.isassigned(a::StaticArray, i::Int...)
1424
ii = LinearIndices(size(a))[i...]
@@ -51,6 +61,17 @@ similar_type(::Type{A},s::Size{S}) where {A<:AbstractArray,S} = similar_type(A,e
5161

5262
similar_type(::A,::Type{T},s::Size{S}) where {A<:AbstractArray,T,S} = similar_type(A,T,s)
5363

64+
# We should be able to deal with SOneTo axes
65+
similar_type(s::SOneTo) = similar_type(typeof(s))
66+
similar_type(::Type{SOneTo{n}}) where {n} = similar_type(SOneTo{n}, Int, Size(n))
67+
68+
similar_type(::A, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A<:AbstractArray} = similar_type(A, eltype(A), shape)
69+
similar_type(::Type{A}, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A<:AbstractArray} = similar_type(A, eltype(A), shape)
70+
71+
similar_type(::A,::Type{T}, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A<:AbstractArray,T} = similar_type(A, T, Size(last.(shape)))
72+
similar_type(::Type{A},::Type{T}, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A<:AbstractArray,T} = similar_type(A, T, Size(last.(shape)))
73+
74+
5475
# Default types
5576
# Generally, use SArray
5677
similar_type(::Type{A},::Type{T},s::Size{S}) where {A<:AbstractArray,T,S} = default_similar_type(T,s,length_val(s))
@@ -98,6 +119,17 @@ similar(::Type{A},::Type{T},s::Size{S}) where {A<:AbstractArray,T,S} = mutable_s
98119
similar(::Type{SA},::Type{T},s::Size{S}) where {SA<:SizedArray,T,S} = sizedarray_similar_type(T,s,length_val(s))(undef)
99120
similar(::Type{A},::Type{T},s::Size{S}) where {A<:Array,T,S} = sizedarray_similar_type(T,s,length_val(s))(undef)
100121

122+
# We should be able to deal with SOneTo axes
123+
similar(::A, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A<:AbstractArray} = similar(A, eltype(A), shape)
124+
similar(::Type{A}, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A<:AbstractArray} = similar(A, eltype(A), shape)
125+
126+
similar(::A,::Type{T}, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A<:AbstractArray,T} = similar(A, T, Size(last.(shape)))
127+
similar(::Type{A},::Type{T}, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A<:AbstractArray,T} = similar(A, T, Size(last.(shape)))
128+
129+
# Handle mixtures of SOneTo and other ranges (probably should make Base more robust here)
130+
similar(::Type{A}, shape::Tuple{AbstractUnitRange, Vararg{AbstractUnitRange}}) where {A<:AbstractArray} = similar(A, length.(shape)) # Jumps back to 2-argument form in Base
131+
similar(::Type{A},::Type{T}, shape::Tuple{AbstractUnitRange, Vararg{AbstractUnitRange}}) where {A<:AbstractArray,T} = similar(A, length.(shape))
132+
101133

102134
@inline reshape(a::StaticArray, s::Size) = similar_type(a, s)(Tuple(a))
103135
@inline reshape(a::AbstractArray, s::Size) = _reshape(a, IndexStyle(a), s)

0 commit comments

Comments
 (0)