How to generate an array by broadcasting an existing function?(any dim)

julia has very useful broadcasting for vector

julia> f(a,b)=a^2+b-1
f (generic function with 1 method)

julia> f(2,3)
6

julia> f.(1:3,6)          # or @. f(1:3,6)
3-element Vector{Int64}:
  6
  9
 14

julia> f.(1:3,6:8)
3-element Vector{Int64}:
  6
 10
 16

julia> A=hcat(f.(1:3,6), f.(1:3,7), f.(1:3,8))
3×3 Matrix{Int64}:
  6   7   8
  9  10  11
 14  15  16

Is there any macro or function can do like

julia> A == @??? f(1:3,6:8)
true

note: the number of parameters of f is no limit.

You could try:

map(t -> f(t...), Iterators.product(1:3, 6:8))
5 Likes

nice answer. thanks.

Aren’t you just looking for

f.(1:3, (6:8)')

?

1 Like

Nice one :smile:
I guess . is missing …!!

f.(1:3, (6:8)')
1 Like

Oops. Thanks, fixed.

1 Like

This is a good answer but seems just satisfy 2-dims array…

Broadcasting (f.(x, y, z, ...)) works for any number of dimensions, and will expand into ℝⁿ (or other n-dimensional spaces), but you need to get your inputs in the right shape first. So if you want z to lie in the third dimension, you can do

z = reshape(1:3, 1, 1, :)

If you need to do this for arbitrarily high dimensions, it becomes tedious, and @greg_plowman’s solutions is more convenient. If your data is already in the right shape, then it’s better to just use f.(x, y, z, ...).

3 Likes

This answer is useful for me. Thanks!

Obviously, it does not want to be an alternative to the solution with product, but maybe could be useful in other cases to have a generalization (perhaps made better) of this type:

g(a,b,c)=a^2+b+c-1
r(p,v)=reshape(v, ntuple(e-> e < p ? 1 : length(v), p))

v1=1:4
v2=6:10
v3=2:5

V=[v1,v2,v3]

g.(map(((i,v),)->r(i,v), enumerate(V))...)

another way to define the position based reshaping function …

r(p,v)=eval(Base.Meta.parse("["*join(v,";"^p)*"]"))