| 324 | }; |
| 325 | |
| 326 | class Shape { |
| 327 | public: |
| 328 | // For Shape, we stick to half-way encapsulation for now: |
| 329 | // we hide the raw dims_ member, but expose it raw by accessors |
| 330 | // because from some brainstorming, it's not at all easy to |
| 331 | // anticipate which flavor of more hermetic encapsulation would |
| 332 | // actually buy us future-proof-ness without being needlessly |
| 333 | // cumbersome. |
| 334 | Shape() {} |
| 335 | Shape(std::initializer_list<int> dim_list) : dims_(dim_list) {} |
| 336 | |
| 337 | void ReplaceDims(std::initializer_list<int> dim_list) { |
| 338 | dims_ = std::vector<int>(dim_list); |
| 339 | } |
| 340 | |
| 341 | const std::vector<int>& dims() const { return dims_; } |
| 342 | std::vector<int>* mutable_dims() { return &dims_; } |
| 343 | const int dimensions_count() const { return dims_.size(); } |
| 344 | |
| 345 | // We still have that one convenience accessor to avoid |
| 346 | // the awkward double bracket issue: shape.dims()[i]. |
| 347 | int dims(int i) const { |
| 348 | // Always check for out-of-bounds accesses, even in optimized builds where |
| 349 | // standard assertions are disabled. Out-of-bounds access here is a common |
| 350 | // occurrence. |
| 351 | CHECK_GE(i, 0); |
| 352 | CHECK_GT(dims_.size(), i); |
| 353 | return dims_[i]; |
| 354 | } |
| 355 | |
| 356 | bool operator==(const Shape& comp) const { |
| 357 | return (this->dims_ == comp.dims()); |
| 358 | } |
| 359 | |
| 360 | bool operator!=(const Shape& comp) const { return !((*this) == comp); } |
| 361 | |
| 362 | private: |
| 363 | std::vector<int> dims_; |
| 364 | }; |
| 365 | |
| 366 | // Base class for all operator classes. |
| 367 | struct Operator { |
no outgoing calls