Skip to content

Commit 246c256

Browse files
committed
Merge branch 'master' of https://github.com/JuliaArrays/StaticArrays.jl into mbaran/matmul-symmetric
2 parents 9fece75 + ad583c9 commit 246c256

22 files changed

+264
-19
lines changed

.github/workflows/benchmark.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
- uses: actions/checkout@v2
1111
- uses: julia-actions/setup-julia@latest
1212
with:
13-
version: 1.3
13+
version: 1.4
1414
- name: Install dependencies
1515
run: julia -e 'using Pkg; pkg"add PkgBenchmark BenchmarkCI@0.1"'
1616
- name: Run benchmarks

.github/workflows/ci.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ jobs:
99
test:
1010
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
1111
runs-on: ${{ matrix.os }}
12+
continue-on-error: ${{ matrix.version == 'nightly' }}
1213
strategy:
1314
matrix:
1415
version:
1516
- '1.0'
1617
- '1.1'
1718
- '1.2'
1819
- '1.3'
20+
- '1.4'
1921
- 'nightly'
2022
os:
2123
- ubuntu-latest
@@ -32,8 +34,10 @@ jobs:
3234
# Don't test on all versions
3335
- {os: 'macOS-latest', version: '1.1'}
3436
- {os: 'macOS-latest', version: '1.2'}
37+
- {os: 'macOS-latest', version: '1.3'}
3538
- {os: 'windows-latest', version: '1.1'}
3639
- {os: 'windows-latest', version: '1.2'}
40+
- {os: 'windows-latest', version: '1.3'}
3741
steps:
3842
- uses: actions/checkout@v1
3943
- uses: julia-actions/setup-julia@latest
@@ -52,7 +56,7 @@ jobs:
5256
- uses: actions/checkout@v1
5357
- uses: julia-actions/setup-julia@latest
5458
with:
55-
version: '1.3'
59+
version: '1.4'
5660
- run: julia --project=docs -e '
5761
using Pkg;
5862
Pkg.develop(PackageSpec(; path=pwd()));

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "StaticArrays"
22
uuid = "90137ffa-7385-5640-81b9-e52037218182"
3-
version = "0.12.2"
3+
version = "0.12.4"
44

55
[deps]
66
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
@@ -11,9 +11,9 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
1111
julia = "1"
1212

1313
[extras]
14+
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
1415
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
1516
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
16-
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
1717

1818
[targets]
1919
test = ["InteractiveUtils", "Test", "BenchmarkTools"]

src/SArray.jl

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,62 @@ end
5050
end
5151
end
5252

53+
54+
@noinline function generator_too_short_error(inds::CartesianIndices, i::CartesianIndex)
55+
error("Generator produced too few elements: Expected exactly $(shape_string(inds)) elements, but generator stopped at $(shape_string(i))")
56+
end
57+
@noinline function generator_too_long_error(inds::CartesianIndices)
58+
error("Generator produced too many elements: Expected exactly $(shape_string(inds)) elements, but generator yields more")
59+
end
60+
61+
shape_string(inds::CartesianIndices) = join(length.(inds.indices), '×')
62+
shape_string(inds::CartesianIndex) = join(Tuple(inds), '×')
63+
64+
@inline throw_if_nothing(x, inds, i) =
65+
(x === nothing && generator_too_short_error(inds, i); x)
66+
67+
@generated function sacollect(::Type{SA}, gen) where {SA <: StaticArray{S}} where {S <: Tuple}
68+
stmts = [:(Base.@_inline_meta)]
69+
args = []
70+
iter = :(iterate(gen))
71+
inds = CartesianIndices(size_to_tuple(S))
72+
for i in inds
73+
el = Symbol(:el, i)
74+
push!(stmts, :(($el,st) = throw_if_nothing($iter, $inds, $i)))
75+
push!(args, el)
76+
iter = :(iterate(gen,st))
77+
end
78+
push!(stmts, :($iter === nothing || generator_too_long_error($inds)))
79+
push!(stmts, :(SA($(args...))))
80+
Expr(:block, stmts...)
81+
end
82+
"""
83+
sacollect(SA, gen)
84+
85+
Construct a statically-sized vector of type `SA`.from a generator
86+
`gen`. `SA` needs to have a size parameter since the length of `vec`
87+
is unknown to the compiler. `SA` can optionally specify the element
88+
type as well.
89+
90+
Example:
91+
92+
sacollect(SVector{3, Int}, 2i+1 for i in 1:3)
93+
sacollect(SMatrix{2, 3}, i+j for i in 1:2, j in 1:3)
94+
sacollect(SArray{2, 3}, i+j for i in 1:2, j in 1:3)
95+
96+
This creates the same statically-sized vector as if the generator were
97+
collected in an array, but is more efficient since no array is
98+
allocated.
99+
100+
Equivalent:
101+
102+
SVector{3, Int}([2i+1 for i in 1:3])
103+
"""
104+
sacollect
105+
106+
@inline (::Type{SA})(gen::Base.Generator) where {SA <: StaticArray} =
107+
sacollect(SA, gen)
108+
53109
@inline SArray(a::StaticArray) = SArray{size_tuple(Size(a))}(Tuple(a))
54110

55111
####################
@@ -66,7 +122,7 @@ Base.dataids(::SArray) = ()
66122

67123
# See #53
68124
Base.cconvert(::Type{Ptr{T}}, a::SArray) where {T} = Base.RefValue(a)
69-
Base.unsafe_convert(::Type{Ptr{T}}, a::Base.RefValue{SArray{S,T,D,L}}) where {S,T,D,L} =
125+
Base.unsafe_convert(::Type{Ptr{T}}, a::Base.RefValue{SA}) where {S,T,D,L,SA<:SArray{S,T,D,L}} =
70126
Ptr{T}(Base.unsafe_convert(Ptr{SArray{S,T,D,L}}, a))
71127

72128
macro SArray(ex)

src/SMatrix.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ end
5252
end
5353
end
5454

55+
@inline SMatrix{M, N, T}(gen::Base.Generator) where {M, N, T} =
56+
sacollect(SMatrix{M, N, T}, gen)
57+
@inline SMatrix{M, N}(gen::Base.Generator) where {M, N} =
58+
sacollect(SMatrix{M, N}, gen)
59+
5560
@inline convert(::Type{SMatrix{S1,S2}}, a::StaticArray{<:Tuple, T}) where {S1,S2,T} = SMatrix{S1,S2,T}(Tuple(a))
5661
@inline SMatrix(a::StaticMatrix{S1, S2}) where {S1, S2} = SMatrix{S1, S2}(Tuple(a))
5762

src/SOneTo.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ function SOneTo{n}(r::AbstractUnitRange) where n
1515
errmsg(r)
1616
end
1717

18+
Base.Tuple(::SOneTo{N}) where N = ntuple(identity, Val(N))
19+
1820
Base.axes(s::SOneTo) = (s,)
1921
Base.size(s::SOneTo) = (length(s),)
2022
Base.length(s::SOneTo{n}) where {n} = n

src/SVector.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ const SVector{S, T} = SArray{Tuple{S}, T, 1, S}
1919
@inline SVector{S}(x::NTuple{S,T}) where {S, T} = SVector{S,T}(x)
2020
@inline SVector{S}(x::T) where {S, T <: Tuple} = SVector{S,promote_tuple_eltype(T)}(x)
2121

22+
@inline SVector{N, T}(gen::Base.Generator) where {N, T} =
23+
sacollect(SVector{N, T}, gen)
24+
@inline SVector{N}(gen::Base.Generator) where {N} =
25+
sacollect(SVector{N}, gen)
26+
2227
# conversion from AbstractVector / AbstractArray (better inference than default)
2328
#@inline convert{S,T}(::Type{SVector{S}}, a::AbstractArray{T}) = SVector{S,T}((a...))
2429

src/abstractarray.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,11 @@ reshape(a::Array, ::Size{S}) where {S} = SizedArray{Tuple{S...}}(a)
185185
@inline copy(a::StaticArray) = typeof(a)(Tuple(a))
186186
@inline copy(a::SizedArray) = typeof(a)(copy(a.data))
187187

188-
@inline reverse(v::StaticVector) = typeof(v)(reverse(Tuple(v)))
188+
@inline reverse(v::StaticVector) = typeof(v)(_reverse(v))
189+
190+
@generated function _reverse(v::StaticVector{N,T}) where {N,T}
191+
return Expr(:tuple, (:(v[$i]) for i = N:(-1):1)...)
192+
end
189193

190194
# TODO permutedims?
191195

src/convert.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
# this covers most conversions and "statically-sized reshapes"
1010
@inline convert(::Type{SA}, sa::StaticArray) where {SA<:StaticArray} = SA(Tuple(sa))
11+
@inline convert(::Type{SA}, sa::StaticArray) where {SA<:Scalar} = SA((sa[],)) # disambiguation
1112
@inline convert(::Type{SA}, sa::SA) where {SA<:StaticArray} = sa
1213
@inline convert(::Type{SA}, x::Tuple) where {SA<:StaticArray} = SA(x) # convert -> constructor. Hopefully no loops...
1314

src/mapreduce.jl

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,17 @@ end
113113
@inline _mapreduce(args::Vararg{Any,N}) where N = _mapfoldl(args...)
114114

115115
@generated function _mapfoldl(f, op, dims::Colon, init, ::Size{S}, a::StaticArray...) where {S}
116+
if prod(S) == 0
117+
if init === _InitialValue
118+
if length(a) == 1
119+
return :(Base.mapreduce_empty(f, op, $(eltype(a[1]))))
120+
else
121+
return :(throw(ArgumentError("reducing over an empty collection is not allowed")))
122+
end
123+
else
124+
return :init
125+
end
126+
end
116127
tmp = [:(a[$j][1]) for j 1:length(a)]
117128
expr = :(f($(tmp...)))
118129
if init === _InitialValue
@@ -291,8 +302,8 @@ end
291302

292303
return quote
293304
@_inline_meta
294-
T = typeof(one(eltype(a)) - one(eltype(a)))
295-
@inbounds return similar_type(a, T, Size($Snew))(tuple($(exprs...)))
305+
elements = tuple($(exprs...))
306+
@inbounds return similar_type(a, eltype(elements), Size($Snew))(elements)
296307
end
297308
end
298309

0 commit comments

Comments
 (0)