Update.
authorFrançois Fleuret <francois@fleuret.org>
Wed, 24 May 2023 13:59:03 +0000 (15:59 +0200)
committerFrançois Fleuret <francois@fleuret.org>
Wed, 24 May 2023 13:59:03 +0000 (15:59 +0200)
eingather.py [new file with mode: 0755]

diff --git a/eingather.py b/eingather.py
new file mode 100755 (executable)
index 0000000..2310c55
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+
+# Any copyright is dedicated to the Public Domain.
+# https://creativecommons.org/publicdomain/zero/1.0/
+
+# Written by Francois Fleuret <francois@fleuret.org>
+
+import re, torch
+
+#####################
+
+
+def eingather(op, src, index):
+    s_src, s_dst = re.search("^([^ ]*) *-> *(.*)", op).groups()
+    s_index = re.search("\(([^)]*)\)", s_src).group(1)
+    s_src = re.sub("\([^)]*\)", "_", s_src)
+
+    shape = tuple(src.size(s_src.index(v)) for v in s_dst)
+
+    idx = []
+
+    for i in range(index.dim()):
+        v = s_index[i]
+        j = s_dst.index(v)
+        a = (
+            torch.arange(index.size(i))
+            .reshape((1,) * j + (-1,) + (1,) * (len(s_dst) - j - 1))
+            .expand(shape)
+        )
+        idx.append(a)
+
+    index = index[idx]
+
+    idx = []
+
+    for i in range(src.dim()):
+        v = s_src[i]
+        if v == "_":
+            idx.append(index)
+        else:
+            j = s_dst.index(v)
+            a = (
+                torch.arange(src.size(i))
+                .reshape((1,) * j + (-1,) + (1,) * (len(s_dst) - j - 1))
+                .expand(shape)
+            )
+            idx.append(a)
+
+    return src[idx]
+
+
+#######################
+
+src = torch.rand(3, 5, 7, 11)
+index = torch.randint(src.size(2), (src.size(3), src.size(1), src.size(3)))
+
+# I want result[a,c,e]=src[c,a,index[e,a,e],e]
+
+result = eingather("ca(eae)e -> ace", src, index)
+
+# Check
+
+error = 0
+
+for a in range(result.size(0)):
+    for c in range(result.size(1)):
+        for e in range(result.size(2)):
+            error += (result[a, c, e] - src[c, a, index[e, a, e], e]).abs()
+
+print(error.item())