Normally I would have implemented this by converting to Tuple and broadcasting like
function Base.mod1(CI::CartesianIndex{N}, MOD::CartesianIndex{N}) where N
CartesianIndex(mod1.(Tuple(CI), Tuple(MOD)))
end
but for some reason this results in allocations so benchmarks poorly relative to the ntuple implementation. Oh well, ntuple it is…
I wasn’t going to post just to say that. What I really wrote in to say is that this function is an example of type piracy and should be avoided except as a pull request to Julia itself. Otherwise, consider naming it something else to avoid the potential for (not so?) hilarious bugs in the future.
This seems like something we could support directly. We have mod(::Int, ::UnitRange); the direct corollary here is mod(::CartesianIndex, ::CartesianIndices).
I was thinking about that. The annoying thing is that we don’t have support for (nor an obvious answer for) mod(::Int, ::StepRange) so couldn’t support all CartesianIndices. But it still seems like a nice generalization in the AbstractUnitRange cases where it would apply. It would probably be accepted as a PR to Base without too much fuss.
Yeah, the most powerful idiom this would enable is mod(i, CartesianIndices(A)), where you can be sure that it’s a CartesianIndices{<:AbstractUnitRange}. I think it’s fine to leave the other cases as a method error.