On Wed, Jan 24, 2024 at 11:02 PM Marten van Kerkwijk <mhvk@astro.utoronto.ca> wrote:
Stack of matrices in this context is a an ndarray in which the last two
dimensions are interpreted as columns and rows of matrices (in that
order), stack of vectors as an ndarray in which the last dimension is
interpreted as column vectors.  (Well, axes in all these functions can
be chosen arbitrarily, but those are the defaults.)

So a simple example for matvec would be a rotation matrix that I'd like
to apply to a large number of vectors (say to points in space); this is
currently not easy.  Complex vectors might be Fourier components.  (Note
that I was rather sloppy in calling it multiplication rather than using
the term vector-matrix product, etc.; it is definitely not element-wise!).

The vector-matrix product comes up a bit less, but as mentioned by
Evgeni in physics there is, e.g., the bra-ket stuff with Hamiltonians
(<\psi | \hat H | \psi>), and in linear least squares one often gets
terms which for real data are written as Xᵀ Z, but for complex would be
Xᴴ Z [1]

Hope this clarifies things!



Thanks, but I'm still confused about the need.
Perhaps the following illustrates why.
With respect to the example you offered, what am I missing?
Alan Isaac

import numpy as np
rng = np.random.default_rng()

rot = np.array([[0,-1],[1,0]])    #a rotation matrix

print("first type of stack of vectors:")
vecs1 = rng.random((2,10))
print(vecs1.shape==(2,10))
result1 = rot.dot(vecs1)

print("second type of stack of vectors:")
rng = np.random.default_rng(314)
vecs2 = vecs1.T
result2 = rot.dot(vecs2.T)
print(f"same result2? {(result1==result2).all()}")

print("third type of stack of vectors:")
vecs3 = np.reshape(vecs2,(10,2,1))
result3 = rot.dot(vecs3.squeeze().T)
print(f"same result3? {(result1==result3).all()}")

print("fourth type of stack of vectors:")
vecs4 = np.reshape(vecs2,(10,1,2))
result4 = rot.dot(vecs4.squeeze().T)
print(f"same result4? {(result1==result4).all()}")