can be optimized `np.sum(v1 * v2, axis=1)` etc is computed multiple times