Skip to content

Commit

Permalink
Merge pull request #81 from jipolanco/abstract-multiarrays
Browse files Browse the repository at this point in the history
Define `AbstractManyPencilArray` type
  • Loading branch information
jipolanco authored May 25, 2023
2 parents 4f4b5f1 + 3e3787f commit 0999ced
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 70 deletions.
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "PencilArrays"
uuid = "0e08944d-e94e-41b1-9406-dcf66b6a9d2e"
authors = ["Juan Ignacio Polanco <[email protected]> and contributors"]
version = "0.17.12"
version = "0.18.0"

[deps]
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
Expand Down Expand Up @@ -29,7 +29,7 @@ Requires = "1"
StaticArrayInterface = "1"
StaticArrays = "1"
StaticPermutations = "0.3"
Strided = "1.1, 2"
Strided = "2"
TimerOutputs = "0.5"
VersionParsing = "1"
julia = "1.7"
1 change: 1 addition & 0 deletions docs/src/PencilArrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ in the PencilFFTs docs.
PencilArray
GlobalPencilArray
PencilArrayCollection
AbstractManyPencilArray
ManyPencilArray
```

Expand Down
156 changes: 88 additions & 68 deletions src/multiarrays.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,91 @@
## Definition of AbstractManyPencilArray

"""
AbstractManyPencilArray{N,M}
Abstract type specifying a container holding `M` different
[`PencilArray`](@ref) views to the same underlying.
All views share the same dimensionality `N`. In principle, their element types
can be different.
A concrete implementation, [`ManyPencilArray`](@ref), is proposed in which all
arrays have the same element type `T`.
"""
abstract type AbstractManyPencilArray{N,M} end

Base.ndims(::AbstractManyPencilArray{N}) where {N} = N

"""
ManyPencilArray{T,N,M}
length(A::AbstractManyPencilArray)
Returns the number of [`PencilArray`](@ref)s wrapped by `A`.
"""
Base.length(::AbstractManyPencilArray{N,M}) where {N,M} = M

"""
Tuple(A::AbstractManyPencilArray) -> (u1, u2, …)
Returns the [`PencilArray`](@ref)s wrapped by `A`.
This can be useful for iterating over all the wrapped arrays.
"""
@inline Base.Tuple(A::AbstractManyPencilArray) = A.arrays

"""
first(A::AbstractManyPencilArray)
Returns the first [`PencilArray`](@ref) wrapped by `A`.
"""
Base.first(A::AbstractManyPencilArray) = first(A.arrays)

"""
last(A::AbstractManyPencilArray)
Returns the last [`PencilArray`](@ref) wrapped by `A`.
"""
Base.last(A::AbstractManyPencilArray) = last(A.arrays)

"""
getindex(A::AbstractManyPencilArray, ::Val{i})
getindex(A::AbstractManyPencilArray, i::Integer)
Returns the i-th [`PencilArray`](@ref) wrapped by `A`.
If possible, the `Val{i}` form should be preferred, as it ensures that the full
type of the returned `PencilArray` is known by the compiler.
See also [`first(::AbstractManyPencilArray)`](@ref), [`last(::AbstractManyPencilArray)`](@ref).
# Example
```julia
A = ManyPencilArray(pencil1, pencil2, pencil3)
# Get the PencilArray associated to `pencil2`.
u2 = A[2]
u2 = A[Val(2)]
```
"""
Base.getindex(A::AbstractManyPencilArray, ::Val{i}) where {i} =
_getindex(Val(i), A.arrays...)
@inline Base.getindex(A::AbstractManyPencilArray, i) = A[Val(i)]

@inline function _getindex(::Val{i}, a, t::Vararg) where {i}
i :: Integer
i <= 0 && throw(BoundsError("index must be >= 1"))
i == 1 && return a
_getindex(Val(i - 1), t...)
end

# This will happen if the index `i` intially passed is too large.
@inline _getindex(::Val) = throw(BoundsError("invalid index"))

# ====================================================================== #
## Concrete implementation: ManyPencilArray

"""
ManyPencilArray{T,N,M} <: AbstractManyPencilArray{N,M}
Container holding `M` different [`PencilArray`](@ref) views to the same
underlying data buffer. All views share the same element type `T` and
Expand All @@ -23,7 +109,7 @@ struct ManyPencilArray{
M, # number of arrays
Arrays <: Tuple{Vararg{PencilArray,M}},
DataVector <: AbstractVector{T},
}
} <: AbstractManyPencilArray{N, M}
data :: DataVector
arrays :: Arrays

Expand Down Expand Up @@ -57,69 +143,3 @@ end
_make_arrays(::DenseVector, ::Dims) = ()

Base.eltype(::ManyPencilArray{T}) where {T} = T
Base.ndims(::ManyPencilArray{T,N}) where {T,N} = N

"""
Tuple(A::ManyPencilArray) -> (u1, u2, …)
Returns the [`PencilArray`](@ref)s wrapped by `A`.
This can be useful for iterating over all the wrapped arrays.
"""
@inline Base.Tuple(A::ManyPencilArray) = A.arrays

"""
length(A::ManyPencilArray)
Returns the number of [`PencilArray`](@ref)s wrapped by `A`.
"""
Base.length(::ManyPencilArray{T,N,M}) where {T,N,M} = M

"""
first(A::ManyPencilArray)
Returns the first [`PencilArray`](@ref) wrapped by `A`.
"""
Base.first(A::ManyPencilArray) = first(A.arrays)

"""
last(A::ManyPencilArray)
Returns the last [`PencilArray`](@ref) wrapped by `A`.
"""
Base.last(A::ManyPencilArray) = last(A.arrays)

"""
getindex(A::ManyPencilArray, ::Val{i})
getindex(A::ManyPencilArray, i::Integer)
Returns the i-th [`PencilArray`](@ref) wrapped by `A`.
If possible, the `Val{i}` form should be preferred, as it ensures that the full
type of the returned `PencilArray` is known by the compiler.
See also [`first(::ManyPencilArray)`](@ref), [`last(::ManyPencilArray)`](@ref).
# Example
```julia
A = ManyPencilArray(pencil1, pencil2, pencil3)
# Get the PencilArray associated to `pencil2`.
u2 = A[2]
u2 = A[Val(2)]
```
"""
Base.getindex(A::ManyPencilArray, ::Val{i}) where {i} =
_getindex(Val(i), A.arrays...)
@inline Base.getindex(A::ManyPencilArray, i) = A[Val(i)]

@inline function _getindex(::Val{i}, a, t::Vararg) where {i}
i :: Integer
i <= 0 && throw(BoundsError("index must be >= 1"))
i == 1 && return a
_getindex(Val(i - 1), t...)
end

# This will happen if the index `i` intially passed is too large.
@inline _getindex(::Val) = throw(BoundsError("invalid index"))

0 comments on commit 0999ced

Please sign in to comment.