Skip to content

Commit e5d8da3

Browse files
Merge pull request #293 from JuliaArrays/safeivdep
add safeivdep
2 parents 81c4a3f + cda2ff2 commit e5d8da3

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

lib/ArrayInterfaceCore/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ArrayInterfaceCore"
22
uuid = "30b0a656-2188-435a-8636-2ec0e6a096e2"
3-
version = "0.1.7"
3+
version = "0.1.8"
44

55
[deps]
66
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

lib/ArrayInterfaceCore/src/ArrayInterfaceCore.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,4 +539,30 @@ ndims_index(@nospecialize T::Type{<:Base.LogicalIndex}) = ndims(fieldtype(T, :ma
539539
ndims_index(T::DataType) = 1
540540
ndims_index(@nospecialize(i)) = ndims_index(typeof(i))
541541

542+
"""
543+
instances_do_not_alias(::Type{T}) -> Bool
544+
545+
Is it safe to `ivdep` arrays containing elements of type `T`?
546+
That is, would it be safe to write to an array full of `T` in parallel?
547+
This is not true for `mutable struct`s in general, where editing one index
548+
could edit other indices.
549+
That is, it is not safe when different instances may alias the same memory.
550+
"""
551+
instances_do_not_alias(::Type{T}) where {T} = Base.isbitstype(T)
552+
553+
"""
554+
indices_do_not_alias(::Type{T<:AbstractArray}) -> Bool
555+
556+
Is it safe to `ivdep` arrays of type `T`?
557+
That is, would it be safe to write to an array of type `T` in parallel?
558+
Examples where this is not true are `BitArray`s or `view(rand(6), [1,2,3,1,2,3])`.
559+
That is, it is not safe whenever different indices may alias the same memory.
560+
"""
561+
indices_do_not_alias(::Type) = false
562+
indices_do_not_alias(::Type{A}) where {T, A<:Base.StridedArray{T}} = instances_do_not_alias(T)
563+
indices_do_not_alias(::Type{Adjoint{T,A}}) where {T, A <: AbstractArray{T}} = indices_do_not_alias(A)
564+
indices_do_not_alias(::Type{Transpose{T,A}}) where {T, A <: AbstractArray{T}} = indices_do_not_alias(A)
565+
indices_do_not_alias(::Type{<:SubArray{<:Any,<:Any,A,I}}) where {
566+
A,I<:Tuple{Vararg{Union{Base.RangeIndex, Base.ReshapedUnitRange, Base.AbstractCartesianIndex}}}} = indices_do_not_alias(A)
567+
542568
end # module

lib/ArrayInterfaceCore/test/runtests.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,18 @@ end
268268
@test @inferred(ArrayInterfaceCore.ndims_index(1)) == 1
269269
end
270270

271+
@testset "indices_do_not_alias" begin
272+
@test ArrayInterfaceCore.instances_do_not_alias(Float64)
273+
@test !ArrayInterfaceCore.instances_do_not_alias(Matrix{Float64})
274+
@test ArrayInterfaceCore.indices_do_not_alias(Matrix{Float64})
275+
@test !ArrayInterfaceCore.indices_do_not_alias(BitMatrix)
276+
@test !ArrayInterfaceCore.indices_do_not_alias(Matrix{Matrix{Float64}})
277+
@test ArrayInterfaceCore.indices_do_not_alias(Adjoint{Float64,Matrix{Float64}})
278+
@test ArrayInterfaceCore.indices_do_not_alias(Transpose{Float64,Matrix{Float64}})
279+
@test ArrayInterfaceCore.indices_do_not_alias(typeof(view(rand(4,4)', 2:3, 1:2)))
280+
@test !ArrayInterfaceCore.indices_do_not_alias(typeof(view(rand(7),ones(Int,7))))
281+
@test !ArrayInterfaceCore.indices_do_not_alias(Adjoint{Matrix{Float64},Matrix{Matrix{Float64}}})
282+
@test !ArrayInterfaceCore.indices_do_not_alias(Transpose{Matrix{Float64},Matrix{Matrix{Float64}}})
283+
@test !ArrayInterfaceCore.indices_do_not_alias(typeof(view(fill(rand(4,4),4,4)', 2:3, 1:2)))
284+
end
285+

0 commit comments

Comments
 (0)