Here's one approach making use of slicing
and summing -
def slicing_summing(a,b,c):
c0 = b[:,1]*c[:,2] - b[:,2]*c[:,1]
c1 = b[:,2]*c[:,0] - b[:,0]*c[:,2]
c2 = b[:,0]*c[:,1] - b[:,1]*c[:,0]
return a[:,0]*c0 + a[:,1]*c1 + a[:,2]*c2
We can replace the first three steps that compute c0, c1, c2
and its stacked version with a one-liner, like so -
b[:,[1,2,0]]*c[:,[2,0,1]] - b[:,[2,0,1]]*c[:,[1,2,0]]
This would create another (n,3)
array, which has to used with a
for sum-reduction resulting in a (n,)
shaped array. With the proposed slicing_summing
method, we are directly getting to that (n,)
shaped array with summing of those three slices and thus avoiding that intermediate (n,3)
array.
Sample run -
In [86]: # Setup inputs
...: n = 871
...: a = np.random.rand(n, 3)
...: b = np.random.rand(n, 3)
...: c = np.random.rand(n, 3)
...:
In [87]: # Original approach
...: omega = np.einsum('ij, ij->i', a, np.cross(b, c))
In [88]: np.allclose(omega, slicing_summing(a,b,c))
Out[88]: True
Runtime test -
In [90]: %timeit np.einsum('ij, ij->i', a, np.cross(b, c))
10000 loops, best of 3: 84.6 µs per loop
In [91]: %timeit slicing_summing(a,b,c)
1000 loops, best of 3: 63 µs per loop