I need to compute the signed area of many triangles in 2D, given by a numpy array of shape (2, 3, n)
(x/y coordinate, node in triangle, number of triangles). I'm looking for a a way to do it fast, and the best I could come up with so far is
import numpy
import perfplot
def six(p):
return (
+p[0][2] * p[1][0]
+ p[0][0] * p[1][1]
+ p[0][1] * p[1][2]
- p[0][2] * p[1][1]
- p[0][0] * p[1][2]
- p[0][1] * p[1][0]
) / 2
def mix(p):
return (
+p[0][2] * (p[1][0] - p[1][1])
+ p[0][0] * (p[1][1] - p[1][2])
+ p[0][1] * (p[1][2] - p[1][0])
) / 2
def mix2(p):
p1 = p[1] - p[1][[1, 2, 0]]
return (+p[0][2] * p1[0] + p[0][0] * p1[1] + p[0][1] * p1[2]) / 2
def cross(p):
e1 = p[:, 1] - p[:, 0]
e2 = p[:, 2] - p[:, 0]
return (e1[0] * e2[1] - e1[1] * e2[0]) / 2
def einsum(p):
return (
+numpy.einsum("ij,ij->j", p[0][[2, 0, 1]], p[1][[0, 1, 2]])
- numpy.einsum("ij,ij->j", p[0][[2, 0, 1]], p[1][[1, 2, 0]])
) / 2
def einsum2(p):
return numpy.einsum("ij,ij->j", p[0][[2, 0, 1]], p[1] - p[1][[1, 2, 0]]) / 2
def einsum3(p):
return (
numpy.einsum(
"ij,ij->j", numpy.roll(p[0], 1, axis=0), p[1] - numpy.roll(p[1], 2, axis=0)
)
/ 2
)
perfplot.save(
"out.png",
setup=lambda n: numpy.random.rand(2, 3, n),
kernels=[six, mix, mix2, cross, einsum, einsum2, einsum3],
n_range=[2 ** k for k in range(19)],
)
Any hints on how make it even more efficient?