1c8b59c046895fa5b6d79f73e0b5817330fcfbfc1A. Unique TensorFlower/* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 3db7478e8998f7703c57a75a950c905ec0cb59d7bJosh LevenbergLicensed under the Apache License, Version 2.0 (the "License"); 4db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenbergyou may not use this file except in compliance with the License. 5db7478e8998f7703c57a75a950c905ec0cb59d7bJosh LevenbergYou may obtain a copy of the License at 6db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 7db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg http://www.apache.org/licenses/LICENSE-2.0 8db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 9db7478e8998f7703c57a75a950c905ec0cb59d7bJosh LevenbergUnless required by applicable law or agreed to in writing, software 10db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenbergdistributed under the License is distributed on an "AS IS" BASIS, 11db7478e8998f7703c57a75a950c905ec0cb59d7bJosh LevenbergWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12db7478e8998f7703c57a75a950c905ec0cb59d7bJosh LevenbergSee the License for the specific language governing permissions and 13db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberglimitations under the License. 14db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg==============================================================================*/ 15db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 16db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#ifndef TENSORFLOW_CORE_FRAMEWORK_TENSOR_SHAPE_H_ 17db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#define TENSORFLOW_CORE_FRAMEWORK_TENSOR_SHAPE_H_ 18db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 19db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#include <string> 20db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 21db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" 229934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower#include "tensorflow/core/framework/types.pb.h" 23db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#include "tensorflow/core/lib/core/errors.h" 24db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#include "tensorflow/core/lib/core/status.h" 25db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#include "tensorflow/core/lib/core/stringpiece.h" 26db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#include "tensorflow/core/lib/gtl/array_slice.h" 27db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#include "tensorflow/core/lib/gtl/inlined_vector.h" 28db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#include "tensorflow/core/lib/strings/strcat.h" 29db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#include "tensorflow/core/platform/logging.h" 30db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 31db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenbergnamespace tensorflow { 32db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 33120c3f11f857ce6da7ae90b3eab943896499dca2A. Unique TensorFlower// START_SKIP_DOXYGEN 34f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingtemplate <class Shape> 35f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingclass TensorShapeIter; 36f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingclass TensorShape; 37e85d3df92deb9d717befdf173966a2913ac2aea0Geoffrey Irvingclass TensorShapeProto; 38f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingclass PartialTensorShape; 39120c3f11f857ce6da7ae90b3eab943896499dca2A. Unique TensorFlower// END_SKIP_DOXYGEN 40120c3f11f857ce6da7ae90b3eab943896499dca2A. Unique TensorFlower 41f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// Internal representation for both TensorShape and PartialTensorShape. 42f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingclass TensorShapeRep { 43db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg public: 44f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving ~TensorShapeRep(); 45df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 46df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower /// Copy the specified shape 47f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving TensorShapeRep(const TensorShapeRep& b); 48f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void operator=(const TensorShapeRep& b); 49df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 50f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower /// Move the specified shape. After moving, <b> is safe for destruction and 51f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower // can be reassigned into, but its dimensions and number of elements can be 52f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower // nonsensical (e.g., negative dimension sizes, or number of elements not 53f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower // properly recomputed). 54f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving TensorShapeRep(TensorShapeRep&& b); 55f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void operator=(TensorShapeRep&& b); 56db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 57f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Clear a tensor shape, producing the scalar shape. 58db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg void Clear(); 59db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 60ffd88925f4a29e68779f5b95eb99d60b40daf184David G. Andersen // Maximum number of dimensions in a tensor. 61f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // It's 254 because 255 = kUnknownRank is used to represent unknown rank. 62f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static constexpr int MaxDimensions() { return 254; } 63db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 64db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg /// \brief Returns the number of elements in the tensor. 65db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg /// 66db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg /// We use `int64` and not `size_t` to be compatible with `Eigen::Tensor` 67f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// which uses `ptrdiff_t`. For PartialTensorShape, -1 means not fully 68f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// defined. 69db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg int64 num_elements() const { return num_elements_; } 70db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 71db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg /// For error messages. 72db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg string DebugString() const; 73d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving static string DebugString(const TensorShapeProto& proto); 74d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving 75df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower void DumpRep() const; // XXX 76e8ee5286a686c6fc3057ba7cf9ba9ef7003789a6Geoffrey Irving 77f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving protected: 78f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // Constructable only via TensorShapeBase 79f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving TensorShapeRep() = default; 80df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 81f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void ClearAllButDataType(); 82e8ee5286a686c6fc3057ba7cf9ba9ef7003789a6Geoffrey Irving 83df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // We use 16 bytes to represent a TensorShape. Because we need to 84df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // be able to support full 64-bit dimension sizes and an arbitrary 85df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // number of dimensions for a Tensor, but most tensor dimensions are 86df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // significantly smaller than 64 bits and most tensors are 1, 2, or 3 87df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // dimensions, we have several representations. 88f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // Rep16: Supports up to 6 dimensions where each dimension is < 2^16 - 1 89f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // Rep32: Supports up to 3 dimensions where each dimension is < 2^32 - 1 901bcebcc665e7e9c280be65899002fd3d5a7456a5Geoffrey Irving // Rep64: Supports arbitrary dimensionality, 64-bit dimensions using 91df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // an out of line vector. 92f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // For PartialTensorShape, a dimension of static_cast<uint??>(-1) is unknown. 93f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // This value is not allowed in TensorShape either for format compatibility. 94df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower struct Rep16 { 95f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving uint16 dims_[6]; 96df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower }; 97df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower struct Rep32 { 98f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving uint32 dims_[3]; 99df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower }; 100df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower struct Rep64 { 101df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower gtl::InlinedVector<int64, 4>* dims_; 102df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower }; 103df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 104f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // We use the max value of uint16 or uint32 to represent unknown shapes, so 105f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // the maximum representable valid shape in these representations is one less. 106f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static const int64 kMaxRep16 = std::numeric_limits<uint16>::max() - 1; 107f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static const int64 kMaxRep32 = std::numeric_limits<uint32>::max() - 1; 108f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static const uint16 kUnknownRep16 = std::numeric_limits<uint16>::max(); 109f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static const uint32 kUnknownRep32 = std::numeric_limits<uint32>::max(); 110df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 111df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower Rep16* as16() { return reinterpret_cast<Rep16*>(buf()); } 112df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower Rep32* as32() { return reinterpret_cast<Rep32*>(buf()); } 113df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower Rep64* as64() { return reinterpret_cast<Rep64*>(buf()); } 114df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 115df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower const Rep16* as16() const { return reinterpret_cast<const Rep16*>(buf()); } 116df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower const Rep32* as32() const { return reinterpret_cast<const Rep32*>(buf()); } 117df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower const Rep64* as64() const { return reinterpret_cast<const Rep64*>(buf()); } 118df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 119df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower enum RepTag { REP16 = 0, REP32 = 1, REP_OUT_OF_LINE = 2 }; 120df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 1219934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower // Since we have a convenient extra byte available, we allow the 1229934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower // Tensor class to store an 8-bit value in this extra storage. This 1239934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower // allows it to store the Tensor's datatype enum value here and avoid 1249934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower // an extra word of storage. 1259934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower friend class Tensor; 1269934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower friend class TensorShapeTestHelper; 1279934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower DataType data_type() const { return static_cast<DataType>(buf()[13]); } 1289934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower void set_data_type(DataType dt) { 1299934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower // We only have 8 bits available to store DataType, so make sure it fits 130f4002dd3cb62d64053bc6097a70f83c718c24af2A. Unique TensorFlower DCHECK_LT(static_cast<uint32>(dt), 256u); 1319934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower buf()[13] = static_cast<uint8>(dt); 1329934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower } 1339934b9c6841ee56368c7cb1d10053f68a02680baA. Unique TensorFlower 134df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // We store the number of dimensions in byte 14, and the RepTag in byte 15. 135f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // Bytes [0..13] vary depending on the representation. 136f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // A value of 255 indicates unknown rank in the PartialTensorShape case. 137f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static const uint8 kUnknownRank = 255; 138df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower uint8 ndims_byte() const { return buf()[14]; } 139df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower void set_ndims_byte(uint8 nd) { buf()[14] = nd; } 140df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 141df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower RepTag tag() const { return static_cast<RepTag>(buf()[15]); } 142df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower void set_tag(RepTag tag) { buf()[15] = static_cast<uint8>(tag); } 143df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 144f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void set_num_elements(int64 n) { num_elements_ = n; } 145f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 146f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving private: 147f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void DestructorOutOfLine(); 148f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void SlowCopyFrom(const TensorShapeRep& b); 149f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 150f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving uint8* buf() { return &u_.buf[0]; } 151f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving const uint8* buf() const { return &u_.buf[0]; } 152f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 153df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower union { 154df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower uint8 buf[16]; 155df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // Force data to be aligned enough for a pointer. 156df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower Rep64* unused_aligner; 157df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower } u_; 158db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg int64 num_elements_; 159db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg}; 160db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 161f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// Base class for TensorShape and PartialTensorShape. 162f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// The class is templatized by either TensorShape or PartialTensorShape to 163f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// allow skipping known/unknown checks in the TensorShape case, but the 164f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// representation is shared exactly for fast conversion. 165f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingtemplate <class Shape> 166f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingclass TensorShapeBase : public TensorShapeRep { 167f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving public: 168f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// \brief Construct a `TensorShapeBase` from the provided sizes. 169f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// REQUIRES: `dim_sizes[i] >= 0` (or >= -1 for PartialTensorShape) 170f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving explicit TensorShapeBase(gtl::ArraySlice<int64> dim_sizes); 171f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving TensorShapeBase(std::initializer_list<int64> dim_sizes) 172f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving : TensorShapeBase(gtl::ArraySlice<int64>(dim_sizes)) {} 173f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 174f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Construct an empty TensorShape, or an unknown rank PartialTensorShape 175f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving TensorShapeBase(); 176f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 177f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving TensorShapeBase(const TensorShapeProto& proto); 178f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 179f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Returns `true` iff `proto` is a valid tensor shape. 180f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // For TensorShape, the proto shape must be fully defined. 181f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static bool IsValid(const TensorShapeProto& proto); 182f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 183f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Returns `OK` iff `proto` is a valid tensor shape, and a descriptive error 184f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// status otherwise. 185f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static Status IsValidShape(const TensorShapeProto& proto); 186f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 187f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// \brief Add a dimension to the end ("inner-most"). 188f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// REQUIRES: `size >= 0` 189f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void AddDim(int64 size); 190f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 191f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Appends all the dimensions from `shape`. 192f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void AppendShape(const TensorShapeBase& shape); 193f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 194f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// \brief Insert a dimension somewhere in the `TensorShape`. 195f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// REQUIRES: `0 <= d <= dims()` 196f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// REQUIRES: `size >= 0` 197f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void InsertDim(int d, int64 size); 198f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 199f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// \brief Modifies the size of the dimension `d` to be `size` 200f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// REQUIRES: `0 <= d < dims()` 201f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// REQUIRES: `size >= 0` 202f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void set_dim(int d, int64 size); 203f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 204f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// \brief Removes dimension `d` from the `TensorShape`. 205f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// REQUIRES: `0 <= d < dims()` 206b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower void RemoveDim(int d) { 207b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower CHECK_GE(d, 0); 208b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower RemoveDimRange(d, d + 1); 209b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower } 210b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower 211b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower /// \brief Removes last `n` dimensions from the `TensorShape`. 212b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower /// REQUIRES: `0 <= n <= dims()` 213b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower void RemoveLastDims(int n) { 214b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower CHECK_LE(n, dims()); 215b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower RemoveDimRange(dims() - n, dims()); 216b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower } 217b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower 218b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower /// \brief Removes the dimensions in range `[begin:end)` from `TensorShape`. 219b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower /// Negative values of `end` are interpreted as `dims() + end + 1` (as in 220b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower /// Python). The same is true for negative values of `begin`. REQUIRES: 221b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower /// `-(dims()+1) <= begin <= dims()` REQUIRES: `-(dims()+1) <= end <= dims()` 222b49aef3c17e39a9c7127477333c7cc76aef57a80A. Unique TensorFlower void RemoveDimRange(int begin, int end); 223f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 224f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Return whether the rank is unknown 225f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving bool unknown_rank() const { 226f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving return kIsPartial && ndims_byte() == kUnknownRank; 227f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving } 228f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 229f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Return the number of dimensions in the tensor. 230f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Can be -1 meaning unknown rank for PartialTensorShape. 231f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving int dims() const { 232f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving uint8 dims = ndims_byte(); 233f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving return kIsPartial && dims == kUnknownRank ? -1 : dims; 234f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving } 235f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 236f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// \brief Returns the number of elements in dimension `d`. 237f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// REQUIRES: `0 <= d < dims()` 238f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // TODO(touts): Rename to `dimension()` to match 239f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // `Eigen::Tensor::dimension()`? 240f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving int64 dim_size(int d) const; 241f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 242f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Returns sizes of all dimensions. 243f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // Returns an empty list for unknown rank PartialTensorShape. 244f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving gtl::InlinedVector<int64, 4> dim_sizes() const; 245f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 246f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Return true iff the rank and all of the dimensions are well defined 247f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // TODO(irving): Rename to is_fully_defined now that it's fast. 248f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving bool IsFullyDefined() const { return !kIsPartial || num_elements() != -1; } 249f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 250f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Fill `*proto` from `*this`. 251f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void AsProto(TensorShapeProto* proto) const; 252f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 253f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// For iterating through the dimensions. 254f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving TensorShapeIter<Shape> begin() const; 255f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving TensorShapeIter<Shape> end() const; 256f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 257f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving private: 258f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void RecomputeNumElements(); 259f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 260f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // True for PartialTensorShape, false for TensorShape 261f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static constexpr bool kIsPartial = 262f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving std::is_same<Shape, PartialTensorShape>::value; 263f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static_assert(kIsPartial || std::is_same<Shape, TensorShape>::value, 264f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving "Shape is neither TensorShape nor PartialTensorShape"); 265f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 266f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // Used by AddDim and MakeShapeHelper. Does no error checking. 267f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void UnsafeAddDim(int64 size, int64 new_num_elements); 268f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 269f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // For use by TensorShapeUtils::MakeShape 270f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving template <class T, class S> 271f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving friend Status MakeShapeHelper(const T*, int64, S*); 272f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving}; 273f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 274f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// Represents the shape of a Tensor. 275f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// 276f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// A tensor's shape is denoted by its number of dimensions and a size for each 277f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// dimension. For example, a Tensor represented by a 3 x 4 matrix would have 278f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// a shape of 2-D, [3,4]. 279f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// 280f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// If you know the exact shape of your Tensor when you create the TensorShape 281f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// object, you can specify it then, or you can create a TensorShape with 282f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// zero dimensions and one element, and call AddDim() to add dimensions later. 283f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingclass TensorShape : public TensorShapeBase<TensorShape> { 284f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving public: 285f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving using TensorShapeBase<TensorShape>::TensorShapeBase; 286f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 287f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Allow a TensorShape to be used as a PartialTensorShape without copying 288f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving operator const PartialTensorShape&() const; // NOLINT(runtime/explicit) 289f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 290f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Returns true if `*this` and `b` have the same sizes. Ignores 291f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// dimension names. 292f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving bool IsSameSize(const TensorShape& b) const; 293f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving bool operator==(const TensorShape& b) const { return IsSameSize(b); } 294f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving bool operator!=(const TensorShape& b) const { return !IsSameSize(b); } 295f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 296f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Fill `*dsizes` from `*this`. 297f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving template <int NDIMS> 298f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving Eigen::DSizes<Eigen::DenseIndex, NDIMS> AsEigenDSizes() const; 299f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 300f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Same as `AsEigenDSizes()` but allows for `NDIMS > dims()` -- in 301f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// which case we pad the rest of the sizes with 1. 302f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving template <int NDIMS> 303f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving Eigen::DSizes<Eigen::DenseIndex, NDIMS> AsEigenDSizesWithPadding() const; 304f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 305f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving private: 306f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // These CHECK fail to ease debugging. 307f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // REQUIRES: dims() == NDIMS 308f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void CheckDimsEqual(int NDIMS) const; 309f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // REQUIRES: dims() >= NDIMS 310f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving void CheckDimsAtLeast(int NDIMS) const; 311f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving}; 312f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 313120c3f11f857ce6da7ae90b3eab943896499dca2A. Unique TensorFlower/// Represents the value of one dimension in a TensorShape. 314db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenbergstruct TensorShapeDim { 315db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg explicit TensorShapeDim(int64 s) : size(s) {} 316d33346a801181cb601a4cfc95f1087e165b19703Vijay Vasudevan int64 size; 317db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg}; 318db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 319120c3f11f857ce6da7ae90b3eab943896499dca2A. Unique TensorFlower// START_SKIP_DOXYGEN 320f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingtemplate <class Shape> 321db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenbergclass TensorShapeIter { 322db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg public: 323f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving TensorShapeIter(const Shape* shape, int d) : shape_(shape), d_(d) {} 324db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg bool operator==(const TensorShapeIter& rhs) { 325db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg DCHECK(shape_ == rhs.shape_); 326db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg return d_ == rhs.d_; 327db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg } 328db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg bool operator!=(const TensorShapeIter& rhs) { 329db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg DCHECK(shape_ == rhs.shape_); 330db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg return d_ != rhs.d_; 331db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg } 332db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg void operator++() { ++d_; } 333db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg TensorShapeDim operator*() { return TensorShapeDim(shape_->dim_size(d_)); } 334db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 335db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg private: 336f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving const Shape* shape_; 337db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg int d_; 338db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg}; 339120c3f11f857ce6da7ae90b3eab943896499dca2A. Unique TensorFlower// END_SKIP_DOXYGEN 340db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 341db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg/// \brief Static helper routines for `TensorShape`. Includes a few common 342db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg/// predicates on a tensor shape. 343db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenbergclass TensorShapeUtils { 344db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg public: 345db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg static bool IsScalar(const TensorShape& shape) { return shape.dims() == 0; } 346db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 347db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg static bool IsVector(const TensorShape& shape) { return shape.dims() == 1; } 348db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 349db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg static bool IsVectorOrHigher(const TensorShape& shape) { 350db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg return shape.dims() >= 1; 351db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg } 352db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 353db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg static bool IsMatrix(const TensorShape& shape) { return shape.dims() == 2; } 354db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 355053fc50b2cbb1979cbed1662c3d964c36fdafecdA. Unique TensorFlower static bool IsSquareMatrix(const TensorShape& shape) { 356053fc50b2cbb1979cbed1662c3d964c36fdafecdA. Unique TensorFlower return shape.dims() == 2 && shape.dim_size(0) == shape.dim_size(1); 357053fc50b2cbb1979cbed1662c3d964c36fdafecdA. Unique TensorFlower } 358053fc50b2cbb1979cbed1662c3d964c36fdafecdA. Unique TensorFlower 359db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg static bool IsMatrixOrHigher(const TensorShape& shape) { 360db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg return shape.dims() >= 2; 361db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg } 362db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 363db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg /// \brief Returns a `TensorShape` whose dimensions are 364db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg /// `dims[0]`, `dims[1]`, ..., `dims[n-1]`. 36596a1afa21c59999c68887550b0c8c27cdf171339David G. Andersen static Status MakeShape(const int32* dims, int64 n, TensorShape* out); 36696a1afa21c59999c68887550b0c8c27cdf171339David G. Andersen static Status MakeShape(const int64* dims, int64 n, TensorShape* out); 3679d6b7680cfcc5b784401d17fef997f0c089038b1A. Unique TensorFlower static Status MakeShape(gtl::ArraySlice<int32> shape, TensorShape* out); 3689d6b7680cfcc5b784401d17fef997f0c089038b1A. Unique TensorFlower static Status MakeShape(gtl::ArraySlice<int64> shape, TensorShape* out); 369f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static Status MakeShape(const int32* dims, int64 n, PartialTensorShape* out); 370f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static Status MakeShape(const int64* dims, int64 n, PartialTensorShape* out); 371f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static Status MakeShape(gtl::ArraySlice<int32> shape, 372f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving PartialTensorShape* out); 373f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static Status MakeShape(gtl::ArraySlice<int64> shape, 374f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving PartialTensorShape* out); 375db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 376725e968a934419eec45b9acaf4bf8dc5f5f0574eGeoffrey Irving static string ShapeListString(const gtl::ArraySlice<TensorShape>& shapes); 377db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 378b5388091998dbeb6641b5d29dbceb825ee359acdA. Unique TensorFlower /// \brief Returns true iff `shape` starts with `prefix`. 379b5388091998dbeb6641b5d29dbceb825ee359acdA. Unique TensorFlower static bool StartsWith(const TensorShape& shape, const TensorShape& prefix); 380b5388091998dbeb6641b5d29dbceb825ee359acdA. Unique TensorFlower 381b5388091998dbeb6641b5d29dbceb825ee359acdA. Unique TensorFlower /// \brief Returns true iff `shape` ends with `suffix`. 382b5388091998dbeb6641b5d29dbceb825ee359acdA. Unique TensorFlower static bool EndsWith(const TensorShape& shape, const TensorShape& suffix); 383cade141580c76b41ba71bdc4b019722e674ab954Eugene Brevdo 384cade141580c76b41ba71bdc4b019722e674ab954Eugene Brevdo /// \brief Returns the product of values in an int64 array, 385cade141580c76b41ba71bdc4b019722e674ab954Eugene Brevdo /// or a failing Status if the array represents a value larger than 386cade141580c76b41ba71bdc4b019722e674ab954Eugene Brevdo /// a `TensorShape` can hold. 387cade141580c76b41ba71bdc4b019722e674ab954Eugene Brevdo static Status NumElements(gtl::ArraySlice<int64> shape, int64* num_elements); 388db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg}; 389db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 390f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// Manages the partially known dimensions of a Tensor and their sizes. 391f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingclass PartialTensorShape : public TensorShapeBase<PartialTensorShape> { 392f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving public: 393f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving PartialTensorShape() {} 394f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving using TensorShapeBase<PartialTensorShape>::TensorShapeBase; 395f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 396f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Add a dimension to the end ("inner-most"), returns a new 397f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// PartialTensorShape. 398f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// REQUIRES: `size >= -1`, where -1 means unknown 399f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving PartialTensorShape Concatenate(int64 size) const; 400f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 401f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Appends all the dimensions from `shape`. Returns a new 402f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// PartialTensorShape. 403f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving PartialTensorShape Concatenate(const PartialTensorShape& shape) const; 404f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 405f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Merges all the dimensions from `shape`. Returns 406f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// `InvalidArgument` error if either `shape` has a different rank 407f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// or if any of the dimensions are incompatible. 408f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving Status MergeWith(const PartialTensorShape& shape, 409f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving PartialTensorShape* result) const; 410f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 411f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Exact equality test. Returns true iff the ranks match (i.e., both are 412f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// unknown, or both are known and equal), and all dimensions are equal (i.e., 413f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// both dimensions are known, or both are known and equal). This is a 414f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// stronger condition that IsCompatibleWith. 415f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving bool IsIdenticalTo(const PartialTensorShape& shape) const; 416f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 417f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// Return true iff the ranks match, and if the 418f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// dimensions all either match or one is unknown. 419f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving bool IsCompatibleWith(const PartialTensorShape& shape) const; 420f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 421f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // Fill `*shape` from `*this`. 422f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // If `*this` is not fully defined, returns false and 423f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // `*shape` is left in an intermediate state. Otherwise 424f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // returns true. 425f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving bool AsTensorShape(TensorShape* shape) const; 426f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 427f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// \brief Returns a `PartialTensorShape` whose dimensions are 428f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// `dims[0]`, `dims[1]`, ..., `dims[n-1]`. Values of -1 are 429f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving /// considered "unknown". 430f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving template <class T> 431f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static Status MakePartialShape(const T* dims, int n, 432f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving PartialTensorShape* out) { 433f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving return TensorShapeUtils::MakeShape(dims, n, out); 434f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving } 435f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving}; 436f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 437f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// \brief Static helper routines for `PartialTensorShape`. Includes a few 438f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving/// common predicates on a partially known tensor shape. 439f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingclass PartialTensorShapeUtils { 440f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving public: 441f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static string PartialShapeListString( 442f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving const gtl::ArraySlice<PartialTensorShape>& shapes); 443f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 444f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static bool AreIdentical(const gtl::ArraySlice<PartialTensorShape>& shapes0, 445f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving const gtl::ArraySlice<PartialTensorShape>& shapes1); 446f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 447f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving static bool AreCompatible(const gtl::ArraySlice<PartialTensorShape>& shapes0, 448f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving const gtl::ArraySlice<PartialTensorShape>& shapes1); 449f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving}; 450f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 451db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg// ---------------------------------------------------------------------------- 452db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg// Template method implementation details below 453db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg// ---------------------------------------------------------------------------- 454db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 455db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenbergtemplate <int NDIMS> 456db7478e8998f7703c57a75a950c905ec0cb59d7bJosh LevenbergEigen::DSizes<Eigen::DenseIndex, NDIMS> TensorShape::AsEigenDSizes() const { 457821920c1f25968f5dfcd2f8999b293ebedf85957A. Unique TensorFlower CheckDimsEqual(NDIMS); 458db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg return AsEigenDSizesWithPadding<NDIMS>(); 459db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg} 460db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 461db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenbergtemplate <int NDIMS> 462db7478e8998f7703c57a75a950c905ec0cb59d7bJosh LevenbergEigen::DSizes<Eigen::DenseIndex, NDIMS> TensorShape::AsEigenDSizesWithPadding() 463db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg const { 464821920c1f25968f5dfcd2f8999b293ebedf85957A. Unique TensorFlower CheckDimsAtLeast(NDIMS); 4654d9ec5ece5771a1982352574ce2cad587644fadaDavid G. Andersen static_assert(NDIMS <= TensorShape::MaxDimensions(), "Too many dimensions"); 466db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg Eigen::DSizes<Eigen::DenseIndex, NDIMS> dsizes; 467db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg for (int d = 0; d < dims(); d++) { 468db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg dsizes[d] = dim_size(d); 469db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg } 470db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg for (int d = dims(); d < NDIMS; d++) { 471db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg dsizes[d] = 1; 472db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg } 473db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg return dsizes; 474db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg} 475db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 476df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower// ---------------------------------------------------------------------------- 477df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower// Inlining of some performance critical routines 478df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower// ---------------------------------------------------------------------------- 479df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 480f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvinginline TensorShapeRep::TensorShapeRep(const TensorShapeRep& b) { 481df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower num_elements_ = b.num_elements_; 482df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower if (b.tag() != REP_OUT_OF_LINE) { 483df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower memcpy(buf(), b.buf(), sizeof(u_.buf)); 484df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // memcpy above Implicitly does: 485df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // set_ndims_byte(b.ndims_byte()); 486df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // set_tag(b.tag()); 487df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower } else { 488df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower set_tag(REP16); // So that SlowCopyFrom does not try to deallocate 489df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower SlowCopyFrom(b); 490df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower } 491df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower} 492df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 493f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvinginline TensorShapeRep::TensorShapeRep(TensorShapeRep&& b) { 494f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower num_elements_ = b.num_elements_; 495f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower memcpy(buf(), b.buf(), sizeof(u_.buf)); 496f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower // memcpy above Implicitly does: 497f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower // set_ndims_byte(b.ndims_byte()); 498f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower // set_tag(b.tag()); 499f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower b.set_tag(REP16); // other shape no longer owns out-of-line data, if any. 500f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower} 501f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower 502f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvinginline TensorShapeRep::~TensorShapeRep() { 503df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower if (tag() == REP_OUT_OF_LINE) { 504b76812c8a84c0efd45342121bfc1cff2b6bb1051A. Unique TensorFlower DestructorOutOfLine(); 505df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower } 506df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower} 507df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 508f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvinginline void TensorShapeRep::operator=(const TensorShapeRep& b) { 509df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower num_elements_ = b.num_elements_; 510df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower if (tag() != REP_OUT_OF_LINE && b.tag() != REP_OUT_OF_LINE) { 511df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower memcpy(buf(), b.buf(), sizeof(u_.buf)); 512df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // memcpy above implicitly also does: 513df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // set_tag(b.tag()); 514df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower // set_ndims_byte(b.ndims_byte()); 515df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower } else { 516df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower SlowCopyFrom(b); 517df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower } 518df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower} 519df66b9fe049cb17e58454f309b662bdaf0d14fdbA. Unique TensorFlower 520f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvinginline void TensorShapeRep::operator=(TensorShapeRep&& b) { 521f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower if (tag() == REP_OUT_OF_LINE) { 522f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower DestructorOutOfLine(); 523f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower } 524f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower num_elements_ = b.num_elements_; 525f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower memcpy(buf(), b.buf(), sizeof(u_.buf)); 526f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower // memcpy above Implicitly does: 527f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower // set_ndims_byte(b.ndims_byte()); 528f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower // set_tag(b.tag()); 529f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower b.set_tag(REP16); // other shape no longer owns out-of-line data, if any. 530f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower} 531f7a662e595f1631c12d15173344ee0f50d2cd9f8A. Unique TensorFlower 532f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvinginline TensorShape::operator const PartialTensorShape&() const { 533f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving // Downcast to the shared representation and upcast to PartialTensorShape 534f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving const TensorShapeRep* rep = this; 535f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving return *static_cast<const PartialTensorShape*>(rep); 536f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving} 537f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 538f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving// Declare explicit instantiations in .cc file 539f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingextern template class TensorShapeBase<TensorShape>; 540f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irvingextern template class TensorShapeBase<PartialTensorShape>; 541f5bbcdf2d05ddc3b24a17ac7fc2cfdf36ef2ee2bGeoffrey Irving 542db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg} // namespace tensorflow 543db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg 544db7478e8998f7703c57a75a950c905ec0cb59d7bJosh Levenberg#endif // TENSORFLOW_CORE_FRAMEWORK_TENSOR_SHAPE_H_ 545