Skip to content

Commit 92287a2

Browse files
committed
added safe version; bikeshed name v2
1 parent cef6354 commit 92287a2

File tree

2 files changed

+112
-27
lines changed

2 files changed

+112
-27
lines changed

src/SArray.jl

Lines changed: 111 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -272,15 +272,20 @@ function promote_rule(::Type{<:SArray{S,T,N,L}}, ::Type{<:SArray{S,U,N,L}}) wher
272272
end
273273

274274
"""
275-
unsafe_squashdims(a::Array{T,N}, ::NTuple{K,Colon))
276-
Gives an Array of SArrays referencing the same memory as A. The first K dimensions are squashed.
277-
This operation may be unsafe in terms of aliasing analysis:
278-
The compiler might mistakenly assume that the two arrays do not overlap, even though they do. See
279-
also `reinterpret`, `reshape` and `unsafe_squashdims`.
275+
unsafe_packdims(a::Array{T,N}; dims::Integer=1)
276+
Gives an `N-dims`-dimensional Array of `dims`-dimensional SArrays
277+
referencing the same memory as A. The first `dims`` dimensions are packed.
278+
This operation may be unsafe in terms of aliasing analysis:
279+
The compiler might mistakenly assume that the memory holding the two arrays'
280+
contents does not overlap, even though they in fact do alias.
281+
On Julia 1.0.*, this operation is perfectly safe, but this is expected
282+
to change in the future.
283+
284+
See also `reinterpret`, `reshape`, `packdims`, `unpackdims` and `unsafe_unpackdims`.
280285
281286
# Examples
282287
```jldoctest
283-
julia> A=reshape(collect(1:8), (2,2,2))
288+
julia> A = reshape(collect(1:8), (2,2,2))
284289
2×2×2 Array{Int64,3}:
285290
[:, :, 1] =
286291
1 3
@@ -290,55 +295,135 @@ julia> A=reshape(collect(1:8), (2,2,2))
290295
5 7
291296
6 8
292297
293-
julia> Asv = unsafe_squashdims(A,(:,:))
298+
julia> A_pack = unsafe_packdims(A; dims=2)
294299
2-element Array{SArray{Tuple{2,2},Int64,2,4},1}:
295300
[1 3; 2 4]
296301
[5 7; 6 8]
297302
298-
julia> A[2,2,1]=-1; A[2,2,1]==Asv[1][2,2]
303+
julia> A[2,2,1]=-1; A[2,2,1]==A_pack[1][2,2]
299304
true
300305
```
301306
"""
302-
@noinline function unsafe_squashdims(a::Array{T,N}, ::NTuple{K,Colon}) where {T,N,K}
307+
@noinline function unsafe_packdims(a::Array{T,N}; dims::Integer=1) where {T,N}
303308
isbitstype(T) || error("$(T) is not a bitstype")
304-
K<N || error("Cannot squash $(K) dims of an $(N)-dim Array")
309+
0<dims<N || error("Cannot pack $(dims) dimensions of an $(N)-dim Array")
310+
dims=Int(dims)
305311
sz = size(a)
306-
sz_sa = ntuple(i->sz[i], K)
307-
satype = SArray{Tuple{sz_sa...}, T, K, prod(sz_sa)}
308-
sz_rest = ntuple(i->sz[K+i], N-K)
309-
restype = Array{satype, N-K}
312+
sz_sa = ntuple(i->sz[i], dims)
313+
satype = SArray{Tuple{sz_sa...}, T, dims, prod(sz_sa)}
314+
sz_rest = ntuple(i->sz[dims+i], N-dims)
315+
restype = Array{satype, N-dims}
310316
ccall(:jl_reshape_array, Any, (Any, Any, Any),restype, a, sz_rest)::restype
311317
end
312318

313319

314320
"""
315-
unsafe_unsquash(A::Array{SArray})
321+
unsafe_unpackdims(A::Array{SArray})
316322
Gives an Array referencing the same memory as A. Its dimension is the sum of the
317-
SArray dimension and dimension of A. This operation may be unsafe in terms of aliasing analysis:
318-
The compiler might mistakenly assume that the two arrays do not overlap, even though they do. See
319-
also `reinterpret`, `reshape` and `unsafe_squashdims`.
323+
SArray dimension and dimension of A, where the SArray dimensions are added in front.
324+
The compiler might mistakenly assume that the memory holding the two arrays'
325+
contents does not overlap, even though they in fact do alias.
326+
On Julia 1.0.*, this operation is perfectly safe, but this is expected
327+
to change in the future.
328+
329+
See also `reinterpret`, `reshape`, `packdims`, `unpackdims` and `unsafe_packdims`.
320330
321331
# Examples
322332
```jldoctest
323-
julia> MM=zeros(SVector{2,Int32},2)
333+
julia> A_pack = zeros(SVector{2,Int32},2)
324334
2-element Array{SArray{Tuple{2},Int32,1,2},1}:
325335
[0, 0]
326336
[0, 0]
327337
328-
julia> M=unsafe_unsquash(MM); M[1,1]=-1; M[2,1]=-2; M
329-
2×2 Array{Int32,2}:
330-
-1 0
331-
-2 0
332-
333-
julia> MM
338+
julia> A = unsafe_unpackdims(A_pack); A[1,1]=-1; A[2,1]=-2; A_pack
334339
2-element Array{SArray{Tuple{2},Int32,1,2},1}:
335340
[-1, -2]
336341
[0, 0]
342+
343+
julia> A_pack
344+
2-element Array{SArray{Tuple{2},Int32,1,2},1}:
345+
[-1, -2]
346+
[0, 0]
337347
```
338348
"""
339-
@noinline function unsafe_unsquash(a::Array{SArray{SZT, T, NDIMS, L},N}) where {T,N,SZT,NDIMS,L}
349+
@noinline function unsafe_unpackdims(a::Array{SArray{SZT, T, NDIMS, L},N}) where {T,N,SZT,NDIMS,L}
340350
isbitstype(T) || error("$(T) is not a bitstype")
341351
dimres = N+NDIMS
342352
szres = (size(eltype(a))..., size(a)...)
343353
ccall(:jl_reshape_array, Any, (Any, Any, Any),Array{T,dimres}, a, szres)::Array{T, dimres}
344354
end
355+
356+
"""
357+
packdims(a::AbstractArray{T,N}; dims::Integer=1)
358+
Gives an `N-dims`-dimensional AbstractArray of `dims`-dimensional SArrays
359+
referencing the same memory as A. The first `dims`` dimensions are packed.
360+
In some contexts, the result may have suboptimal performance characteristics.
361+
362+
See also `reinterpret`, `reshape`, `unsafe_packdims`, `unpackdims` and `unsafe_unpackdims`.
363+
364+
# Examples
365+
```jldoctest
366+
julia> A = reshape(collect(1:8), (2,2,2))
367+
2×2×2 Array{Int64,3}:
368+
[:, :, 1] =
369+
1 3
370+
2 4
371+
372+
[:, :, 2] =
373+
5 7
374+
6 8
375+
376+
julia> A_pack = packdims(A; dims=2)
377+
2-element reinterpret(SArray{Tuple{2,2},Int64,2,4}, ::Array{Int64,1}):
378+
[1 3; 2 4]
379+
[5 7; 6 8]
380+
381+
julia> A[2,2,1]=-1; A[2,2,1]==A_pack[1][2,2]
382+
true
383+
```
384+
"""
385+
@noinline function packdims(a::AbstractArray{T,N}; dims::Integer=1) where {T,N}
386+
isbitstype(T) || error("$(T) is not a bitstype")
387+
0<dims<N || error("Cannot pack $(dims) dimensions of an $(N)-dim Array")
388+
dims=Int(dims)
389+
sz = size(a)
390+
sz_sa = ntuple(i->sz[i], dims)
391+
satype = SArray{Tuple{sz_sa...}, T, dims, prod(sz_sa)}
392+
sz_rest = ntuple(i->sz[dims+i], N-dims)
393+
return reshape(reinterpret(satype, reshape(a, length(a))), sz_rest)
394+
end
395+
396+
397+
"""
398+
unpackdims(A::AbstractArray{SArray})
399+
Gives an Array referencing the same memory as A. Its dimension is the sum of the
400+
SArray dimension and dimension of A, where the SArray dimensions are added in front.
401+
In some contexts, the result may have suboptimal performance characteristics.
402+
403+
404+
See also `reinterpret`, `reshape`, `packdims`, `unpackdims` and `unsafe_packdims`.
405+
406+
# Examples
407+
```jldoctest
408+
julia> A_pack = zeros(SVector{2,Int32},2)
409+
2-element Array{SArray{Tuple{2},Int32,1,2},1}:
410+
[0, 0]
411+
[0, 0]
412+
413+
julia> A = unpackdims(A_pack); A[1,1]=-1; A[2,1]=-2; A_pack
414+
2-element Array{SArray{Tuple{2},Int32,1,2},1}:
415+
[-1, -2]
416+
[0, 0]
417+
418+
julia> A
419+
2×2 reshape(reinterpret(Int32, ::Array{SArray{Tuple{2},Int32,1,2},1}), 2, 2) with eltype Int32:
420+
-1 0
421+
-2 0
422+
```
423+
"""
424+
@noinline function unpackdims(a::AbstractArray{SArray{SZT, T, NDIMS, L},N}) where {T,N,SZT,NDIMS,L}
425+
isbitstype(T) || error("$(T) is not a bitstype")
426+
dimres = N+NDIMS
427+
szres = (size(eltype(a))..., size(a)...)
428+
return reshape(reinterpret(T, a),szres)
429+
end

src/StaticArrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export @MVector, @MMatrix, @MArray
3939

4040
export similar_type
4141
export push, pop, pushfirst, popfirst, insert, deleteat, setindex
42-
export unsafe_squashdims, unsafe_unsquash
42+
export packdims, unpackdims, unsafe_packdims, unsafe_unpackdims
4343

4444
"""
4545
abstract type StaticArray{S, T, N} <: AbstractArray{T, N} end

0 commit comments

Comments
 (0)