Broadcast over a specific dimension of array

Hello, Julians!

I have a 3 dimensional complex F64 array. I want to run the inv() over the inner two dimensions and broadcast along the outer dimension. When I try simple broadcasting inv.(A) I get different results than if I do a for-loop. How do I specify the dimension I want to broadcast over?

The easiest solution would be to have a Vector of Matrix objects. That said, it is very rare for inv to be the best method for solving problems. What’s the usecase?

2 Likes

Broadcast is completely point-wise. That is, it applies to every element in the array, not slices thereof. Thus if you want to use broadcast across slices like this, you need to use some sort of array-of-arrays structure.

1 Like

The matrix represents the mapping of inputs to outputs of an electrical circuit. The outer dimension represents how that matrix changes at different frequency points. So to flip the mapping from outputs to inputs I just need to invert the matrix, but I want to do it at each frequency so I need to invert the matrix for each matrix along the array. It sounds like a 1D array of 2D arrays would be the best approach.

It looks like mapslices might be the method I was looking for. But, perhaps there is a better way to do what I want than iterating over the outer dimension?

1 Like

It sounds like a 1D array of 2D arrays would be the best approach.

map or broadcast with eachslice can yield a 1D array of 2D arrays:

julia> x = rand(3,3,4);

julia> inv.(eachslice(x, dims=3))
4-element Array{Array{Float64,2},1}:
 [-1.6590312226570239 2.0793019606694854 0.5372029679273337; -0.41725584494784745 -0.16227671804840568 1.4356241190356016; 3.1581583049406534 -1.8836845469856938 -1.3709070403858319]
 [2.2504272336124984 -1.3387872100956475 -1.3175125593090484; -0.6955200736976385 2.3904260659293395 -0.15231503786728723; -1.6588907341843613 -5.504678105886818 6.354210163417449]
 [-6.522265014454815 11.007596635562658 -0.8997442890195426; 5.918653872368978 -6.235209223176827 -0.20055712370467133; 3.1672517888989637 -7.134447496548201 2.0670158780550607]
 [1.257897188987869 0.5534734488273791 -3.7933556798265524; -1.3639997740291203 1.2156395483916482 3.2530995922802717; -1.1021239862109267 -3.2404755836203387 21.985361866828296]

julia> map(inv, eachslice(x, dims=3))
4-element Array{Array{Float64,2},1}:
 [-1.6590312226570239 2.0793019606694854 0.5372029679273337; -0.41725584494784745 -0.16227671804840568 1.4356241190356016; 3.1581583049406534 -1.8836845469856938 -1.3709070403858319]
 [2.2504272336124984 -1.3387872100956475 -1.3175125593090484; -0.6955200736976385 2.3904260659293395 -0.15231503786728723; -1.6588907341843613 -5.504678105886818 6.354210163417449]
 [-6.522265014454815 11.007596635562658 -0.8997442890195426; 5.918653872368978 -6.235209223176827 -0.20055712370467133; 3.1672517888989637 -7.134447496548201 2.0670158780550607]
 [1.257897188987869 0.5534734488273791 -3.7933556798265524; -1.3639997740291203 1.2156395483916482 3.2530995922802717; -1.1021239862109267 -3.2404755836203387 21.985361866828296]

julia> mapslices(inv, x, dims=(1,2))
3×3×4 Array{Float64,3}:
[:, :, 1] =
 -1.65903    2.0793     0.537203
 -0.417256  -0.162277   1.43562
  3.15816   -1.88368   -1.37091

[:, :, 2] =
  2.25043  -1.33879  -1.31751
 -0.69552   2.39043  -0.152315
 -1.65889  -5.50468   6.35421

[:, :, 3] =
 -6.52227  11.0076   -0.899744
  5.91865  -6.23521  -0.200557
  3.16725  -7.13445   2.06702

[:, :, 4] =
  1.2579    0.553473  -3.79336
 -1.364     1.21564    3.2531
 -1.10212  -3.24048   21.9854
1 Like

Thanks, everyone, for the help.

1 Like

I found this thread because I had the same question, essentialy. I was not satisfied with the answers because I wanted

  • a view
  • high performance

So I created a typestable, zero allocation (so it is fast) method for selectdim. Like selectdim it returns a view. Unlike Julia’s version, its second argument must be a Val.

@generated function Base.selectdim(a,::Val{d},i) where{d}
    precols = ()
    pstcols = ()
    for i = 1:d-1
        precols = (precols...,:)
    end
    for i = 1:ndims(a)-d
        pstcols = (pstcols...,:)
    end
    return quote
        return view(a,$(precols...),i,$(pstcols...))
    end
end

a = randn(2,4,5)
g = selectdim(a,Val(3),2)  # view to a[:,:,2]