Skip to content

docfix reinterpret #502

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 51 additions & 8 deletions docs/src/pages/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,16 +241,59 @@ Another common way of storing the same data is as a 3×`N` `Matrix{Float64}`.
Rather conveniently, such types have *exactly* the same binary layout in memory,
and therefore we can use `reinterpret` to convert between the two formats
```julia
function svectors(x::Matrix{Float64})
@assert size(x,1) == 3
reinterpret(SVector{3,Float64}, x, (size(x,2),))
function svectors(x::Matrix{T}, ::Val{N}) where {T,N}
size(x,1) == N || throw("sizes mismatch")
isbitstype(T) || throw("use for bitstypes only")
reinterpret(SVector{N,T}, reshape(x, length(x)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use vec(x) rather than reshape here.

end
```
Such a conversion does not copy the data, rather it refers to the *same* memory
referenced by two different Julia `Array`s. Arguably, a `Vector` of `SVector`s
is preferable to a `Matrix` because (a) it provides a better abstraction of the
objects contained in the array and (b) it allows the fast *StaticArrays* methods
to act on elements.
Such a conversion does not copy the data, rather it refers to the *same* memory.
Arguably, a `Vector` of `SVector`s is often preferable to a `Matrix` because
(a) it provides a better abstraction of the objects contained in the array and
(b) it allows the fast *StaticArrays* methods to act on elements

However, the resulting object is a Base.ReinterpretArray, not an Array, which may carry some
runtime penalty on every single access. If you can afford the memory for a copy and can live with
the non-shared mutation semantics, then it is better to pull a copy by e.g.
```julia
function svectorscopy(x::Matrix{T}, ::Val{N}) where {T,N}
size(x,1) == N || throw("sizes mismatch")
isbitstype(T) || throw("use for bitstypes only")
res = Vector{SVector{N,T}}(undef, size(x,2))
ccall(:memcpy, Ptr{Cvoid}, (Ptr{Cvoid}, Ptr{Cvoid}, Csize_t), pointer(res), pointer(x), sizeof(x))
res
end
```
For example:
```
julia> M=reshape(collect(1:6), (2,3))
2×3 Array{Int64,2}:
1 3 5
2 4 6

julia> svectors(M, Val{2}())
3-element reinterpret(SArray{Tuple{2},Int64,1,2}, ::Array{Int64,1}):
[1, 2]
[3, 4]
[5, 6]

julia> svectorscopy(M, Val{2}())
3-element Array{SArray{Tuple{2},Int64,1,2},1}:
[1, 2]
[3, 4]
[5, 6]
```
If you absolutely insist on obtaining a `Vector{<:SVector}` referencing the same memory
and don't mind a maintenance nightmare and data-corrupting tbaa-related bugs appearing in
julia 1.1 or later, then you can obtain this by
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😆

This might seem a little confusing to the uninitiated. I wonder if we should write this in a slightly more factual way?

```julia
function unmaintainable_svectors(x::Matrix{T}, ::Val{N}) where {T,N}
size(x,1) == N || throw("sizes mismatch")
isbitstype(T) || throw("use for bitstypes only")
ccall(:jl_reshape_array, Vector{SVector{N,T}}, (Any,Any,Any), Vector{SVector{N,T}}, x, (size(x,2),))
end
```


### Working with mutable and immutable arrays

Expand Down