| 178 | } |
| 179 | |
| 180 | Maybe<void> CheckInplaceShapeCanExpandTo(const Shape& shape, const Shape& expand_shape) { |
| 181 | if (shape == expand_shape) { return Maybe<void>::Ok(); } |
| 182 | |
| 183 | CHECK_OR_RETURN(expand_shape.NumAxes() >= shape.NumAxes()) |
| 184 | << Error::RuntimeError() << "Can not expand origin shape " << shape.ToString() << " to " |
| 185 | << expand_shape.ToString() << " in an inplace operation"; |
| 186 | |
| 187 | int shift = expand_shape.NumAxes() - shape.NumAxes(); |
| 188 | for (int i = expand_shape.NumAxes() - 1; i >= 0; --i) { |
| 189 | int index = i - shift; |
| 190 | if (index >= 0) { |
| 191 | int dim_a = expand_shape.At(i); |
| 192 | int dim_b = shape.At(index); |
| 193 | // NOTE(lixiang): When a dimension of tensor a and tensor b are not equal in size, dim_a needs |
| 194 | // to be greater than or equal 0, and dim_b should be equal to 1. |
| 195 | CHECK_OR_RETURN(!(dim_a != dim_b && (dim_a < 0 || dim_b != 1))) |
| 196 | << Error::RuntimeError() << "Tensor with shape " << expand_shape.ToString() |
| 197 | << " doesn't match the broadcast shape in an inplace operation"; |
| 198 | } else { |
| 199 | // For 0-size tensor, expand_shape.At(i) can equal to 0. |
| 200 | CHECK_OR_RETURN(expand_shape.At(i) >= 0); // NOLINT(maybe-need-error-msg) |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | return Maybe<void>::Ok(); |
| 205 | } |
| 206 | |
| 207 | Optional<Stride> ComputeStride(const Shape& shape, const Stride& stride, |
| 208 | const Shape& target_shape) { |
no test coverage detected