Infix macros and tuple valued function broadcasting

Hello :slight_smile:

I am using modular arithmetic extensively and there are two things that I am missing:

  1. Possibility to define infix macro. I’d like to use syntax like this:

x = H .* Y @mod 17

and @mod macro would translate the whole expression to

x = mod.(H .* Y, 17)

  1. Broadcasting functions that return tuples should return tuple of array, not array of tuples

julia> A = [2,4,5];
julia> x = divrem.(A, 3)
3-element Array{Tuple{Int64,Int64},1}:
(0, 2)
(1, 1)
(1, 2)

I’d prefer to use syntax like this:

x, r = divrem.(A, 3)

It’s not a big deal, cause i can do:

x, r = div.(A, 3), rem.(A, 3)

Anyway, tuple of arrays make more sense for me here and I am not the only one bothered by this behaviour: Bug with divrem?

Welcome to JuliaLang Discourse!
In the first one, what about broadcasting %?

x=[30, 31,32]
x .% 17 

About the second one, broadcasting spits a result of similar size as the input, so giving two arrays comes against this. Maybe using an alternative option?

a1 = similar(x) 
a2 = similar(x) 
for i in eachindex(x) 
  a1[i], a2[i] =divrem(x[i], 17)
end
3 Likes

Hi @longemen3000 , thanks for the answer!
I am afraid that mod and % (rem) are two different mathematical operations - differences occur for negative numbers and it affects algorithms I am working on. I can implement ‘mod’ with ‘rem’, but I want to keep things simple, that’s why I am looking for alternative syntax.
Your answer gave me an idea - I’ll try to define custom infix operator that is doing ‘mod’ and I’ll broadcast result array with it.
The second suggestion is good, cause it scans x array once, probably I will do something similar inside a helper method.

Another option is to use an struct and overload an infix operator,here is a quick draft

struct Mod <: Integer
n::Int
end
Base.:%(a::Real, b::Mod) = mod(a, b.n)
x .% Mod(17)

As a bonus, it looks like your proposal

3 Likes

I think it’s confusing to reuse % for ‘mod’.
I found that there are plenty not used infix operator symbols to use, check ‘prec-times’ list.

⨸(a, b) = mod(a, b)
A = [-5, 5, 3, -2]
res = (2 .+ A .* 2) .⨸ 3

works well for me.
Thanks!

And I like the idea of Mod struct. Using operator from ‘prec-plus’ list allows to skip parentheses.

struct Mod{T<:Integer} <: Integer n::T end
⧺(a, b::Mod) = mod(a, b.n)
A = [-5, 5, 3, -2]
res = 2 .+ A .* 2 .⧺Mod(3)

1 Like