index format: 'ij,jk->ik' (result after '->' is mandatory!); return: input data, result data, full set
| 208 | // index format: 'ij,jk->ik' (result after '->' is mandatory!); return: input data, result data, |
| 209 | // full set |
| 210 | Array<MultiIndex> compute_multi_indices(const string &index_signature, |
| 211 | const Array<shared_ptr<CoefficientFunction>> &cfs) { |
| 212 | Array<MultiIndex> idx_sets(cfs.Size() + 2); |
| 213 | MultiIndex *current_idx_set = idx_sets.begin(); |
| 214 | MultiIndex &full_idx_set = idx_sets[cfs.Size() + 1]; |
| 215 | |
| 216 | Array<char> chars; |
| 217 | Array<int> char_counts; |
| 218 | Array<char> free_symbols; |
| 219 | |
| 220 | int subset_cnt = 0; |
| 221 | int subset_idx = 0; |
| 222 | bool result_section = false; |
| 223 | |
| 224 | for_each(begin(index_signature), end(index_signature), [&](const char idx) { |
| 225 | if (idx == '>' || idx == '\0') |
| 226 | return; |
| 227 | |
| 228 | if (idx == '-') |
| 229 | result_section = true; |
| 230 | |
| 231 | if (idx == ',' || idx == '-') { |
| 232 | ++current_idx_set; |
| 233 | ++subset_cnt; |
| 234 | subset_idx = 0; |
| 235 | return; |
| 236 | } |
| 237 | |
| 238 | if ((idx < 'a' || idx > 'z') && (idx < 'A' || idx > 'Z')) |
| 239 | throw NG_EXCEPTION("invalid index character detected -- use only a-z, A-Z"); |
| 240 | |
| 241 | if (!chars.Contains(idx)) { |
| 242 | if (result_section) |
| 243 | throw NG_EXCEPTION("detected 'result indices' not present in the inputs"); |
| 244 | |
| 245 | size_t subset_dim_i = 1; |
| 246 | if (cfs[subset_cnt]->Dimensions().Size() <= 1) |
| 247 | if (subset_idx > 1) |
| 248 | throw NG_EXCEPTION("tensor order mismatch"); |
| 249 | else |
| 250 | subset_dim_i = cfs[subset_cnt]->Dimension(); |
| 251 | else if (subset_idx + 1 > cfs[subset_cnt]->Dimensions().Size()) |
| 252 | throw NG_EXCEPTION("tensor order mismatch"); |
| 253 | else |
| 254 | subset_dim_i = cfs[subset_cnt]->Dimensions()[subset_idx]; |
| 255 | |
| 256 | full_idx_set.Append(Index{idx, chars.Size(), subset_dim_i}); |
| 257 | current_idx_set->Append(full_idx_set[chars.Size()]); |
| 258 | chars.Append(idx); |
| 259 | char_counts.Append(1); |
| 260 | } else if (!result_section && cfs[subset_cnt]->Dimensions()[subset_idx] != |
| 261 | full_idx_set[chars.Pos(idx)].dim) { |
| 262 | throw NG_EXCEPTION("dimensions of contracted indices do not match"); |
| 263 | } else { |
| 264 | current_idx_set->Append(full_idx_set[chars.Pos(idx)]); |
| 265 | if (!result_section) |
| 266 | char_counts[chars.Pos(idx)] += 1; |
| 267 | } |