From 532aebdaf05aa0c981ca7df3a2af5e353e5c35a5 Mon Sep 17 00:00:00 2001 From: Andy Ferris Date: Tue, 18 Dec 2018 21:37:51 +1000 Subject: [PATCH 1/2] Make `strides` into a generic trait Returns `nothing` for non-strided arrays, otherwise gives the give strides in memory. Useful as an extensible trait in generic contexts, and simpler to overload for cases of "wrapped" arrays where "stridedness" can be deferred to the parent rather than a complex (and inextensible) method signature. --- base/abstractarray.jl | 16 +++++++++++----- base/permuteddimsarray.jl | 6 +++++- stdlib/LinearAlgebra/src/adjtrans.jl | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 2733b52222e37..dbfe08f493d75 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -511,7 +511,9 @@ end """ strides(A) -Return a tuple of the memory strides in each dimension. +Return a tuple of the memory strides in each dimension, for an `AbstractArray` with a +strided memory layout. For arrays with a non-strided layout (such as sparse arrays), return +`nothing`. See also: [`stride`](@ref). @@ -523,7 +525,7 @@ julia> strides(A) (1, 3, 12) ``` """ -function strides end +strides(::AbstractArray) = nothing """ stride(A, k::Integer) @@ -544,9 +546,13 @@ julia> stride(A,3) ``` """ function stride(A::AbstractArray, k::Integer) - st = strides(A) - k ≤ ndims(A) && return st[k] - return sum(st .* size(A)) + str = strides(A) + if str === nothing + return nothing + else + k ≤ ndims(A) && return st[k] + return sum(st .* size(A)) + end end @inline size_to_strides(s, d, sz...) = (s, size_to_strides(s * d, sz...)...) diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index ea966c44efc38..0d3ffa43ba465 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -62,7 +62,11 @@ Base.pointer(A::PermutedDimsArray, i::Integer) = throw(ArgumentError("pointer(A, function Base.strides(A::PermutedDimsArray{T,N,perm}) where {T,N,perm} s = strides(parent(A)) - ntuple(d->s[perm[d]], Val(N)) + if s === nothing + return nothing + else + return ntuple(d->s[perm[d]], Val(N)) + end end Base.elsize(::Type{<:PermutedDimsArray{<:Any, <:Any, <:Any, <:Any, P}}) where {P} = Base.elsize(P) diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index 6c3e1f1125537..a28871326bf4c 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -218,6 +218,25 @@ parent(A::AdjOrTrans) = A.parent vec(v::TransposeAbsVec{<:Number}) = parent(v) vec(v::AdjointAbsVec{<:Real}) = parent(v) +# provide strides, but only for eltypes that are directly stored in memory (i.e. unaffected +# by recursive `adjoint` and `transpose`, being `Real` and `Number` respectively) +function Base.strides(a::Union{Adjoint{<:Real, <:AbstractVector}, Transpose{<:Number, <:AbstractVector}}) + str = strides(a.parent) + if str === nothing + return nothing + else + return (1, str[1]) + end +end +function Base.strides(a::Union{Adjoint{<:Real, <:AbstractMatrix}, Transpose{<:Number, <:AbstractMatrix}}) + str = strides(a.parent) + if str === nothing + return nothing + else + return (str[2], str[1]) + end +end + ### concatenation # preserve Adjoint/Transpose wrapper around vectors # to retain the associated semantics post-concatenation From 39e6e6db6952d971e9d5fdbd962f388ba22903b4 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Tue, 5 Nov 2024 21:56:10 +0100 Subject: [PATCH 2/2] Remove the whitespace --- base/abstractarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 38431b2f1323a..3816ee926dead 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -599,7 +599,7 @@ function stride(A::AbstractArray, k::Integer) return nothing else k ≤ ndims(A) && return st[k] - ndims(A) == 0 && return 1 + ndims(A) == 0 && return 1 return sum(st .* size(A)) end end