-
Notifications
You must be signed in to change notification settings - Fork 46
Defined pointer method. #170
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
Conversation
Codecov Report
@@ Coverage Diff @@
## master #170 +/- ##
=======================================
Coverage 99.22% 99.23%
=======================================
Files 4 4
Lines 257 260 +3
=======================================
+ Hits 255 258 +3
Misses 2 2
Continue to review full report at Codecov.
|
|
The unit test fails on Julia 1.0. LoopVectorization doesn't support 1.0, so I don't need that test to pass... I'll try just checking version, and only checking |
|
@jishnub Mind reviewing? |
src/OffsetArrays.jl
Outdated
| A | ||
| end | ||
|
|
||
| @inline Base.unsafe_convert(::Type{Ptr{T}}, A::OffsetArray{T}) where {T} = pointer(parent(A)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this call unsafe_convert instead of pointer? I'm not really clear on when one vs the other should be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not either. But after pondering for a couple minutes, I think unsafe_convert would be a little better so that we can specify that we want a Ptr{T}.
The advantage of pointer would be that it falls back on unsafe_convert, giving another option for authors to intercept. I don't really know why anyone would want pointer or unsafe_convert to return a different value. Maybe a different type, in which case we want to use unsafe_convert anyway.
|
Let's do this. We might want to rename |
|
Great, sounds good. Calling [`Ref(array[, index])`](@ref Ref) is generally preferable to this function as it guarantees validity.
julia> v = rand(100);
julia> vo = OffsetArray(v, -10);
julia> v[1]
0.9243160384144822
julia> v[11]
0.7486822152275043
julia> Ref(vo, 1)[]
0.7486822152275043I'm not sure if a docstring like this: """
pointer(array [, offset])
Get the native address of an array or string, optionally at a given location `offset`.
This function is "unsafe". Be careful to ensure that a Julia reference to
`array` exists as long as this pointer will be used. The [`GC.@preserve`](@ref)
macro should be used to protect the `array` argument from garbage collection
within a given block of code.
Calling [`Ref(array[, index])`](@ref Ref) is generally preferable to this function as it guarantees validity.
"""would be confusing without explaining Also, perhaps we should add that |
|
I guess the other option would be to keep it an index and return a pointer that is shifted so that |
|
Yeah, that'd probably be better. |
|
You probably already know this, but just in case you're not familiar with the differences in linear indexing for 1-d arrays vs all others: https://docs.julialang.org/en/v1/devdocs/offset-arrays/#Linear-indexing-(LinearIndices). |
|
Actually turns out the default definition for function pointer(x::AbstractArray{T}, i::Integer) where T
@_inline_meta
unsafe_convert(Ptr{T}, x) + Int(_memory_offset(x, i))::Int
end
# The distance from pointer(x) to the element at x[I...] in bytes
function _memory_offset(x::AbstractArray, I::Vararg{Any,N}) where {N}
J = _to_subscript_indices(x, I...)
return sum(map((i, s, o)->s*(i-o), J, strides(x), Tuple(first(CartesianIndices(x)))))*elsize(x)
endonce we define: Base.strides(A::OffsetArray) = strides(parent(A))
Base.elsize(::Type{OffsetArray{T,N,A}}) where {T,N,A} = Base.elsize(A)That means: julia> using OffsetArrays, Test
julia> a = OffsetVector(collect(10:20), 9);
julia> @test 12 == a[12] == unsafe_load(pointer(a), 12 + (1 - firstindex(a))) == unsafe_load(pointer(a, 12))
Test Passed
julia> A = OffsetArray(reshape(collect(10:130), (11,11)), 9, 9);
julia> @test 21 == A[12] == unsafe_load(pointer(A), 12) == unsafe_load(pointer(A, 12))
Test Passed
julia> @test 61 == A[52] == unsafe_load(pointer(A), 52) == unsafe_load(pointer(A, 52))
Test PassedI added those methods and a few more tests.
Thanks, I observed and worked around that behavior in |
timholy
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice! Merge at will.
|
Shall we tag a release? |
|
Done. I'm never sure whether to call these patch releases or minor releases (is this a new feature or a bug fix?), but I went with the version bump you supplied. |
This is needed for transitioning LoopVectorization to being based off ArrayInterface.