@@ -19,6 +19,15 @@ using ArrayLayouts: ArrayLayouts
19
19
return ArrayLayouts. layout_getindex (a, I... )
20
20
end
21
21
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
+
22
31
# TODO : Maybe define as `ArrayLayouts.layout_getindex(a, I...)` or
23
32
# `invoke(getindex, Tuple{AbstractArray,Vararg{Any}}, a, I...)`.
24
33
# TODO : Use `MethodError`?
28
37
return error (" Not implemented." )
29
38
end
30
39
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
+
31
61
@interface :: AbstractArrayInterface function Broadcast. BroadcastStyle (type:: Type )
32
62
return Broadcast. DefaultArrayStyle {ndims(type)} ()
33
63
end
203
233
# # @interface ::AbstractMatrixInterface function Base.*(a1, a2)
204
234
# # return ArrayLayouts.mul(a1, a2)
205
235
# # 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