| 161 | } |
| 162 | |
| 163 | common_dims common_dims::compute(const std::vector<std::size_t>& dims1, |
| 164 | const std::vector<std::size_t>& dims2) |
| 165 | { |
| 166 | assert(elements(dims1) > 0); |
| 167 | assert(elements(dims1) == elements(dims2)); |
| 168 | common_dims cd; |
| 169 | common_dim_state state1{dims1, cd.axes_map1}; |
| 170 | common_dim_state state2{dims2, cd.axes_map2}; |
| 171 | while(not state1.is_end() and not state2.is_end()) |
| 172 | { |
| 173 | auto d1 = state1.get(); |
| 174 | auto d2 = state2.get(); |
| 175 | if(d1 == d2) |
| 176 | { |
| 177 | state1.add_axes(1, cd.dims.size()); |
| 178 | state2.add_axes(1, cd.dims.size()); |
| 179 | state1.rem = 1; |
| 180 | state2.rem = 1; |
| 181 | cd.dims.push_back(d1); |
| 182 | state1.next(); |
| 183 | state2.next(); |
| 184 | } |
| 185 | else if(d1 < d2) |
| 186 | { |
| 187 | if(not compute_common_dim(cd.dims, state1, state2)) |
| 188 | return {}; |
| 189 | } |
| 190 | else // if(d1 > d2) |
| 191 | { |
| 192 | if(not compute_common_dim(cd.dims, state2, state1)) |
| 193 | return {}; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | // Handle case where one state has a remainder that equals the next dimension |
| 198 | // In this case, the dimension was already added as a remainder, we just need the axes mapping |
| 199 | auto handle_remaining_dimension = [&cd](common_dim_state& state) { |
| 200 | if(not state.is_end() and state.rem != 1 and state.get() == 1) |
| 201 | { |
| 202 | // The remainder already added to cd_dims matches this dimension |
| 203 | // Add a single axes mapping |
| 204 | state.axes_map->push_back({cd.dims.size() - 1}); |
| 205 | state.next(); |
| 206 | } |
| 207 | }; |
| 208 | |
| 209 | handle_remaining_dimension(state1); |
| 210 | handle_remaining_dimension(state2); |
| 211 | |
| 212 | assert(elements(dims1) == elements(cd.dims)); |
| 213 | return cd; |
| 214 | } |
| 215 | |
| 216 | const std::vector<std::vector<std::size_t>>* common_dims::get_axes_map(std::size_t n) const |
| 217 | { |