Build an inverse map of dimension indices. Three conditions must hold for the result to be meaningful. First, no duplicate letter labels in each label string. Second, the number of dots in dimout_labels >= that in in_labels. Third, dots are contiguous in each label string.
(in_labels: str, out_labels: str)
| 135 | |
| 136 | |
| 137 | def build_view(in_labels: str, out_labels: str) -> list[int]: |
| 138 | ''' |
| 139 | Build an inverse map of dimension indices. Three conditions must hold for |
| 140 | the result to be meaningful. |
| 141 | First, no duplicate letter labels in each label string. |
| 142 | Second, the number of dots in dimout_labels >= that in in_labels. |
| 143 | Third, dots are contiguous in each label string. |
| 144 | |
| 145 | Parameters |
| 146 | ---------- |
| 147 | in_labels: |
| 148 | The dimension labels to map to |
| 149 | out_labels: |
| 150 | The dimension labels to map from |
| 151 | |
| 152 | Returns |
| 153 | ------- |
| 154 | The inverse map from out_labels to in_labels. The length of the inverse map equals that of |
| 155 | out_labels. -1 is filled if there's no matching input dimension for a specific label. |
| 156 | |
| 157 | Examples |
| 158 | -------- |
| 159 | in_labels = 'ij..', out_labels = '..ji' |
| 160 | inv_map = [2, 3, 1, 0] |
| 161 | in_labels = 'ij..', out_labels = '..kji' |
| 162 | inv_map = [2, 3, -1, 1, 0] |
| 163 | ''' |
| 164 | |
| 165 | inv_map = [-1] * len(out_labels) |
| 166 | |
| 167 | # First build the broadcast dimension mapping |
| 168 | # Find the broadcast index range in out_labels |
| 169 | r = re.search(r'\.+', out_labels) |
| 170 | if r is not None: |
| 171 | start, end = r.start(), r.end() |
| 172 | s = re.search(r'\.+', in_labels) |
| 173 | # fill the broadcast dimension indices from right to left. |
| 174 | if s: |
| 175 | for ax, dim in zip( |
| 176 | range(start, end)[::-1], range(s.start(), s.end())[::-1] |
| 177 | ): |
| 178 | inv_map[ax] = dim |
| 179 | # Now work on non-broadcast dimensions |
| 180 | it = itertools.chain(range(start), range(end, len(out_labels))) |
| 181 | else: |
| 182 | it = iter(range(len(out_labels))) |
| 183 | |
| 184 | for i in it: |
| 185 | inv_map[i] = in_labels.find(out_labels[i]) |
| 186 | |
| 187 | return inv_map |
| 188 | |
| 189 | |
| 190 | def build_global_view( |