5050 end
5151end
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
68124Base. 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
72128macro SArray (ex)
0 commit comments