11using ArrayLayouts: LayoutArray
2- using BlockArrays: blockisequal
3- using DerivableInterfaces: @interface , AbstractArrayInterface, interface
4- using GPUArraysCore: @allowscalar
2+ using BlockArrays: AbstractBlockVector, Block
53using LinearAlgebra: Adjoint, Transpose
6- using SparseArraysBase: SparseArraysBase, SparseArrayStyle
7-
8- # Returns `Vector{<:CartesianIndices}`
9- function union_stored_blocked_cartesianindices (as:: Vararg{AbstractArray} )
10- combined_axes = combine_axes (axes .(as)... )
11- stored_blocked_cartesianindices_as = map (as) do a
12- return blocked_cartesianindices (axes (a), combined_axes, eachblockstoredindex (a))
13- end
14- return ∪ (stored_blocked_cartesianindices_as... )
15- end
16-
17- # This is used by `map` to get the output axes.
18- # This is type piracy, try to avoid this, maybe requires defining `map`.
19- # # Base.promote_shape(a1::Tuple{Vararg{BlockedUnitRange}}, a2::Tuple{Vararg{BlockedUnitRange}}) = combine_axes(a1, a2)
20-
21- reblock (a) = a
224
5+ # TODO : Make this more general, independent of `AbstractBlockSparseArray`.
236# If the blocking of the slice doesn't match the blocking of the
247# parent array, reblock according to the blocking of the parent array.
258function reblock (
@@ -32,12 +15,14 @@ function reblock(
3215 return @view parent (a)[UnitRange {Int} .(parentindices (a))... ]
3316end
3417
18+ # TODO : Make this more general, independent of `AbstractBlockSparseArray`.
3519function reblock (
3620 a:: SubArray{<:Any,<:Any,<:AbstractBlockSparseArray,<:Tuple{Vararg{NonBlockedArray}}}
3721)
3822 return @view parent (a)[map (I -> I. array, parentindices (a))... ]
3923end
4024
25+ # TODO : Make this more general, independent of `AbstractBlockSparseArray`.
4126function reblock (
4227 a:: SubArray {
4328 <: Any ,
@@ -50,77 +35,18 @@ function reblock(
5035 return @view parent (a)[map (I -> Vector (I. blocks), parentindices (a))... ]
5136end
5237
53- # `map!` specialized to zero-dimensional inputs.
54- function map_zero_dim! end
55-
56- @interface :: AbstractArrayInterface function map_zero_dim! (
57- f, a_dest:: AbstractArray , a_srcs:: AbstractArray...
58- )
59- @allowscalar a_dest[] = f .(map (a_src -> a_src[], a_srcs)... )
38+ function Base. map! (f, a_dest:: AbstractArray , a_srcs:: AnyAbstractBlockSparseArray... )
39+ @interface interface (a_dest, a_srcs... ) map! (f, a_dest, a_srcs... )
6040 return a_dest
6141end
62-
63- # TODO : Move to `blocksparsearrayinterface/map.jl`.
64- # TODO : Rewrite this so that it takes the blocking structure
65- # made by combining the blocking of the axes (i.e. the blocking that
66- # is used to determine `union_stored_blocked_cartesianindices(...)`).
67- # `reblock` is a partial solution to that, but a bit ad-hoc.
68- # # TODO : Make this an `@interface AbstractBlockSparseArrayInterface` function.
69- @interface interface:: AbstractBlockSparseArrayInterface function Base. map! (
70- f, a_dest:: AbstractArray , a_srcs:: AbstractArray...
71- )
72- if iszero (ndims (a_dest))
73- @interface interface map_zero_dim! (f, a_dest, a_srcs... )
74- return a_dest
75- end
76-
77- a_dest, a_srcs = reblock (a_dest), reblock .(a_srcs)
78- for I in union_stored_blocked_cartesianindices (a_dest, a_srcs... )
79- BI_dest = blockindexrange (a_dest, I)
80- BI_srcs = map (a_src -> blockindexrange (a_src, I), a_srcs)
81- # TODO : Investigate why this doesn't work:
82- # block_dest = @view a_dest[_block(BI_dest)]
83- block_dest = blocks_maybe_single (a_dest)[Int .(Tuple (_block (BI_dest)))... ]
84- # TODO : Investigate why this doesn't work:
85- # block_srcs = ntuple(i -> @view(a_srcs[i][_block(BI_srcs[i])]), length(a_srcs))
86- block_srcs = ntuple (length (a_srcs)) do i
87- return blocks_maybe_single (a_srcs[i])[Int .(Tuple (_block (BI_srcs[i])))... ]
88- end
89- subblock_dest = @view block_dest[BI_dest. indices... ]
90- subblock_srcs = ntuple (i -> @view (block_srcs[i][BI_srcs[i]. indices... ]), length (a_srcs))
91- # TODO : Use `map!!` to handle immutable blocks.
92- map! (f, subblock_dest, subblock_srcs... )
93- # Replace the entire block, handles initializing new blocks
94- # or if blocks are immutable.
95- blocks (a_dest)[Int .(Tuple (_block (BI_dest)))... ] = block_dest
96- end
42+ function Base. map! (f, a_dest:: AnyAbstractBlockSparseArray , a_srcs:: AbstractArray... )
43+ @interface interface (a_dest, a_srcs... ) map! (f, a_dest, a_srcs... )
9744 return a_dest
9845end
99-
100- # TODO : Move to `blocksparsearrayinterface/map.jl`.
101- @interface :: AbstractBlockSparseArrayInterface function Base. mapreduce (
102- f, op, as:: AbstractArray... ; kwargs...
46+ function Base. map! (
47+ f, a_dest:: AnyAbstractBlockSparseArray , a_srcs:: AnyAbstractBlockSparseArray...
10348)
104- # TODO : Define an `init` value based on the element type.
105- return @interface interface (blocks .(as)... ) mapreduce (
106- block -> mapreduce (f, op, block), op, blocks .(as)... ; kwargs...
107- )
108- end
109-
110- # TODO : Move to `blocksparsearrayinterface/map.jl`.
111- @interface :: AbstractBlockSparseArrayInterface function Base. iszero (a:: AbstractArray )
112- # TODO : Just call `iszero(blocks(a))`?
113- return @interface interface (blocks (a)) iszero (blocks (a))
114- end
115-
116- # TODO : Move to `blocksparsearrayinterface/map.jl`.
117- @interface :: AbstractBlockSparseArrayInterface function Base. isreal (a:: AbstractArray )
118- # TODO : Just call `isreal(blocks(a))`?
119- return @interface interface (blocks (a)) isreal (blocks (a))
120- end
121-
122- function Base. map! (f, a_dest:: AbstractArray , a_srcs:: AnyAbstractBlockSparseArray... )
123- @interface interface (a_srcs... ) map! (f, a_dest, a_srcs... )
49+ @interface interface (a_dest, a_srcs... ) map! (f, a_dest, a_srcs... )
12450 return a_dest
12551end
12652
0 commit comments