3 # Any copyright is dedicated to the Public Domain.
4 # https://creativecommons.org/publicdomain/zero/1.0/
6 # Written by Francois Fleuret <francois@fleuret.org>
13 def eingather(op, src, *indexes):
14 s_src, s_dst = re.search("^([^ ]*) *-> *(.*)", op).groups()
15 s_indexes = re.findall("\(([^)]*)\)", s_src)
16 s_src = re.sub("\([^)]*\)", "_", s_src)
18 all_sizes = tuple(d for s in ( src, ) + indexes for d in s.size())
19 s_all = "".join([s_src] + s_indexes)
20 shape = tuple(all_sizes[s_all.index(v)] for v in s_dst)
25 for i in range(src.dim()):
28 index, s_index = indexes[n_index], s_indexes[n_index]
33 for i in range(index.dim()):
37 torch.arange(index.size(i))
38 .reshape((1,) * j + (-1,) + (1,) * (len(s_dst) - j - 1))
43 index = index[sub_idx]
48 torch.arange(src.size(i))
49 .reshape((1,) * j + (-1,) + (1,) * (len(s_dst) - j - 1))
57 #######################
59 src = torch.rand(3, 5, 7, 11)
60 index1 = torch.randint(src.size(2), (src.size(3), src.size(1), src.size(3)))
61 index2 = torch.randint(src.size(3), (src.size(1),))
63 # I want result[a, c, e] = src[c, a, index1[e, a, e], index2[a], e]
65 result = eingather("ca(eae)(a) -> ace", src, index1, index2)
71 for a in range(result.size(0)):
72 for c in range(result.size(1)):
73 for e in range(result.size(2)):
74 error += (result[a, c, e] - src[c, a, index1[e, a, e], index2[a]]).abs()