Validate input dimensions and populate unnamed labels and their label counts.
| 206 | |
| 207 | // Validate input dimensions and populate unnamed labels and their label counts. |
| 208 | Status ProcessDimensions(const OpInputList& inputs, |
| 209 | const gtl::InlinedVector<bool, 2>& input_has_ellipsis, |
| 210 | const bool output_has_ellipsis, |
| 211 | OperandLabels* input_labels, Labels* output_labels, |
| 212 | std::vector<DimensionType>* label_types, |
| 213 | OperandLabelCounts* input_label_counts, |
| 214 | LabelCounts* output_label_counts, |
| 215 | LabelToDimSizes* label_to_dim_sizes) { |
| 216 | if (inputs.size() != input_labels->size()) { |
| 217 | return errors::InvalidArgument("Expected ", input_labels->size(), |
| 218 | " inputs but got: ", inputs.size()); |
| 219 | } |
| 220 | const int num_inputs = inputs.size(); |
| 221 | |
| 222 | // We infer the number of broadcasting dimensions by taking the maximum rank |
| 223 | // among the broadcasting subshapes of the input. |
| 224 | int max_bcast_dims = 0; |
| 225 | const int num_named_labels = label_types->size(); |
| 226 | label_to_dim_sizes->resize(num_named_labels); |
| 227 | for (int i = 0; i < num_inputs; ++i) { |
| 228 | Labels* labels = &(*input_labels)[i]; |
| 229 | |
| 230 | if (!input_has_ellipsis[i]) { |
| 231 | if (inputs[i].dims() != labels->size()) { |
| 232 | return errors::InvalidArgument("Expected input ", i, " to have rank ", |
| 233 | labels->size(), |
| 234 | " but got: ", inputs[i].dims()); |
| 235 | } |
| 236 | for (int label_idx = 0; label_idx < labels->size(); ++label_idx) { |
| 237 | const int label = (*labels)[label_idx]; |
| 238 | TF_RETURN_IF_ERROR(RecordLabelToDimension(label, label_idx, inputs[i], |
| 239 | label_to_dim_sizes)); |
| 240 | } |
| 241 | continue; |
| 242 | } |
| 243 | |
| 244 | // Input has an ellipsis. |
| 245 | if (inputs[i].dims() + 1 < labels->size()) { |
| 246 | return errors::InvalidArgument( |
| 247 | "Expected input ", i, " to have rank at least ", labels->size() - 1, |
| 248 | " but got: ", inputs[i].dims()); |
| 249 | } |
| 250 | int ellipsis_axis = -1; |
| 251 | const int num_bcast_dims = inputs[i].dims() - labels->size() + 1; |
| 252 | for (int label_idx = 0; label_idx < labels->size(); ++label_idx) { |
| 253 | const int label = (*labels)[label_idx]; |
| 254 | if (label == kEllipsisLabel) { |
| 255 | ellipsis_axis = label_idx; |
| 256 | continue; |
| 257 | } |
| 258 | // Current label is not an ellipsis. |
| 259 | const int axis = |
| 260 | label_idx + (ellipsis_axis == -1 ? 0 : num_bcast_dims - 1); |
| 261 | TF_RETURN_IF_ERROR( |
| 262 | RecordLabelToDimension(label, axis, inputs[i], label_to_dim_sizes)); |
| 263 | } |
| 264 | // Found an ellipsis. Replace 'kEllipsisLabel' with broadcasting dimensions. |
| 265 | if (ellipsis_axis != -1) { |
no test coverage detected