@@ -19,6 +19,15 @@ using ArrayLayouts: ArrayLayouts
1919 return ArrayLayouts. layout_getindex (a, I... )
2020end
2121
22+ @interface interface:: AbstractArrayInterface function Base. setindex! (
23+ a:: AbstractArray , value, I...
24+ )
25+ # TODO : Change to this once broadcasting in `@interface` is supported:
26+ # @interface interface a[I...] .= value
27+ @interface interface map! (identity, @view (a[I... ]), value)
28+ return a
29+ end
30+
2231# TODO : Maybe define as `ArrayLayouts.layout_getindex(a, I...)` or
2332# `invoke(getindex, Tuple{AbstractArray,Vararg{Any}}, a, I...)`.
2433# TODO : Use `MethodError`?
2837 return error (" Not implemented." )
2938end
3039
40+ # TODO : Make this more general, use `Base.to_index`.
41+ @interface interface:: AbstractArrayInterface function Base. getindex (
42+ a:: AbstractArray{<:Any,N} , I:: CartesianIndex{N}
43+ ) where {N}
44+ return @interface interface getindex (a, Tuple (I)... )
45+ end
46+
47+ # TODO : Use `MethodError`?
48+ @interface :: AbstractArrayInterface function Base. setindex! (
49+ a:: AbstractArray{<:Any,N} , value, I:: Vararg{Int,N}
50+ ) where {N}
51+ return error (" Not implemented." )
52+ end
53+
54+ # TODO : Make this more general, use `Base.to_index`.
55+ @interface interface:: AbstractArrayInterface function Base. setindex! (
56+ a:: AbstractArray{<:Any,N} , value, I:: CartesianIndex{N}
57+ ) where {N}
58+ return @interface interface setindex! (a, value, Tuple (I)... )
59+ end
60+
3161@interface :: AbstractArrayInterface function Broadcast. BroadcastStyle (type:: Type )
3262 return Broadcast. DefaultArrayStyle {ndims(type)} ()
3363end
203233# # @interface ::AbstractMatrixInterface function Base.*(a1, a2)
204234# # return ArrayLayouts.mul(a1, a2)
205235# # end
236+
237+ # Concatenation
238+
239+ axis_cat (a1:: AbstractUnitRange , a2:: AbstractUnitRange ) = Base. OneTo (length (a1) + length (a2))
240+ function axis_cat (
241+ a1:: AbstractUnitRange , a2:: AbstractUnitRange , a_rest:: AbstractUnitRange...
242+ )
243+ return axis_cat (axis_cat (a1, a2), a_rest... )
244+ end
245+
246+ unval (x) = x
247+ unval (:: Val{x} ) where {x} = x
248+
249+ function cat_axes (as:: AbstractArray... ; dims)
250+ return ntuple (length (first (axes .(as)))) do dim
251+ return if dim in unval (dims)
252+ axis_cat (map (axes -> axes[dim], axes .(as))... )
253+ else
254+ axes (first (as))[dim]
255+ end
256+ end
257+ end
258+
259+ function cat! end
260+
261+ # Represents concatenating `args` over `dims`.
262+ struct Cat{Args<: Tuple{Vararg{AbstractArray}} ,dims}
263+ args:: Args
264+ end
265+ to_cat_dims (dim:: Integer ) = Int (dim)
266+ to_cat_dims (dim:: Int ) = (dim,)
267+ to_cat_dims (dims:: Val ) = to_cat_dims (unval (dims))
268+ to_cat_dims (dims:: Tuple ) = dims
269+ Cat (args:: AbstractArray... ; dims) = Cat {typeof(args),to_cat_dims(dims)} (args)
270+ cat_dims (:: Cat{<:Any,dims} ) where {dims} = dims
271+
272+ function Base. axes (a:: Cat )
273+ return cat_axes (a. args... ; dims= cat_dims (a))
274+ end
275+ Base. eltype (a:: Cat ) = promote_type (eltype .(a. args)... )
276+ function Base. similar (a:: Cat )
277+ ax = axes (a)
278+ elt = eltype (a)
279+ # TODO : This drops GPU information, maybe use MemoryLayout?
280+ return similar (arraytype (interface (a. args... ), elt), ax)
281+ end
282+
283+ # https://github.com/JuliaLang/julia/blob/v1.11.1/base/abstractarray.jl#L1748-L1857
284+ # https://docs.julialang.org/en/v1/base/arrays/#Concatenation-and-permutation
285+ # This is very similar to the `Base.cat` implementation but handles zero values better.
286+ function cat_offset! (
287+ a_dest:: AbstractArray , offsets, a1:: AbstractArray , a_rest:: AbstractArray... ; dims
288+ )
289+ inds = ntuple (ndims (a_dest)) do dim
290+ dim in unval (dims) ? offsets[dim] .+ axes (a1, dim) : axes (a_dest, dim)
291+ end
292+ a_dest[inds... ] = a1
293+ new_offsets = ntuple (ndims (a_dest)) do dim
294+ dim in unval (dims) ? offsets[dim] + size (a1, dim) : offsets[dim]
295+ end
296+ cat_offset! (a_dest, new_offsets, a_rest... ; dims)
297+ return a_dest
298+ end
299+ function cat_offset! (a_dest:: AbstractArray , offsets; dims)
300+ return a_dest
301+ end
302+
303+ @interface :: AbstractArrayInterface function cat! (
304+ a_dest:: AbstractArray , as:: AbstractArray... ; dims
305+ )
306+ offsets = ntuple (zero, ndims (a_dest))
307+ # TODO : Fill `a_dest` with zeros if needed using `zero!`.
308+ cat_offset! (a_dest, offsets, as... ; dims)
309+ return a_dest
310+ end
311+
312+ @interface interface:: AbstractArrayInterface function Base. cat (as:: AbstractArray... ; dims)
313+ a_dest = similar (Cat (as... ; dims))
314+ @interface interface cat! (a_dest, as... ; dims)
315+ return a_dest
316+ end
317+
318+ # TODO : Use `@derive` instead:
319+ # ```julia
320+ # @derive (T=AbstractArray,) begin
321+ # cat!(a_dest::AbstractArray, as::T...; dims)
322+ # end
323+ # ```
324+ function cat! (a_dest:: AbstractArray , as:: AbstractArray... ; dims)
325+ return @interface interface (as... ) cat! (a_dest, as... ; dims)
326+ end
0 commit comments