Specifying broadcast in reduce operations

Writing a new CircShiftedArrays package that specified its own BroadcastStyle, I have the trouble that reduce operations such as sum do not get affected by my overloaded functions.
I overloaded copyto! and materialize! for my broadcasttype{CircArrayStyle}, but it seems like a sum partial reduce operation such as

c = CircShiftedArray(rand(10,10))
sum(c, dims=1)

does not trigger any of those. Does anly one know the right function to overload? Would this be some odd form of reduce or mapreduce? Or do I need to specify also copy(::CircShiftedArray) or materialize(::CircShiftedArray) or which function may be missing?
The point is, that these reduce operations need to know something about the mixed-up indices in the CircShiftedArray or at least allocate the correct result-type.

I did find a solution, which is make the result-type of the 3-argument version of similar depend on wether the size is changed, but this sounds a bit like a hack. Yet it does seem to work.
Does anyone know a better place?

As a workaround (probably there is a better way): Maybe you could create a CircShiftedArray( fill(nothing, 10, 10) ) and check the stacktrace to see where you could link in?

I don’t think sum should call any broadcast functions. To customise what it does, you probably want to overload mapreducedim! or one of its friends. To just customise how the output array is allocated, try Base.reducedim_initarray.

1 Like

sum is even mentioned in an example in the AbstractArray interface, so an alternative to overloading the directly used methods is to use the existing ones for AbstractArray by defining the relevant interface methods, including the nominally “optional” methods like similar. I wouldn’t know exactly which interface methods you would need, that would depend on the array’s properties and the methods you would use (for example, immutable arrays don’t even need setindex! despite it being nominally required). I figure that you need at least getindex and size for AbstractArray iteration, which sum and reduce need, and similar for the right output array type after axis-wise reductions, so you’re at least on the right track.

This is what I did at first. Indeed “similar” is called and if I return a CircShiftedArray, everything seemed to work well. But then this broke the code for slicing. E.g. v[1:2,1:2]. The trouble there is that similar does not get any information about the slicing position, it just gets the final size via the dims argument, but the position would be needed to adjust the final shift. For reduce operations to work this shift needs to correspond to the array to reduce. So I think @mcabbot 's suggestion is probably the way to go.

As for getindex and setindex these are, of course, overloaded, but the reason for all of this work is to avoid them being called almost entirely, as this breaks the CuArray performance (and also the mulitthreading performance). For the most part the code achieves this, but I also did not yet figure out, where to hook in for slicing operations such as myshiftedarray[1:2,2:3]. For some reason the debugger unfortunately does not stop in getindex, which would have helped to find out where to interfere.