1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 16 #ifndef TENSORFLOW_CORE_UTIL_SPARSE_DIM_COMPARATOR_H_ 17 #define TENSORFLOW_CORE_UTIL_SPARSE_DIM_COMPARATOR_H_ 18 19 #include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" 20 #include "tensorflow/core/framework/bounds_check.h" 21 #include "tensorflow/core/lib/gtl/array_slice.h" 22 #include "tensorflow/core/platform/logging.h" 23 #include "tensorflow/core/platform/types.h" 24 25 namespace tensorflow { 26 namespace sparse { 27 28 ///////////////// 29 // DimComparator 30 ///////////////// 31 // 32 // Helper class, mainly used by the IndexSortOrder. This comparator 33 // can be passed to e.g. std::sort, or any other sorter, to sort two 34 // rows of an index matrix according to the dimension(s) of interest. 35 // The dimensions to sort by are passed to the constructor as "order". 36 // 37 // Example: if given index matrix IX, two rows ai and bi, and order = {2,1}. 38 // operator() compares 39 // IX(ai,2) < IX(bi,2). 40 // If IX(ai,2) == IX(bi,2), it compares 41 // IX(ai,1) < IX(bi,1). 42 // 43 // This can be used to sort a vector of row indices into IX according to 44 // the values in IX in particular columns (dimensions) of interest. 45 class DimComparator { 46 public: 47 typedef typename gtl::ArraySlice<int64> VarDimArray; 48 DimComparator(const TTypes<int64>::Matrix & ix,const VarDimArray & order,const VarDimArray & shape)49 DimComparator(const TTypes<int64>::Matrix& ix, const VarDimArray& order, 50 const VarDimArray& shape) 51 : ix_(ix), order_(order), dims_(shape.size()) { 52 DCHECK_GT(order.size(), size_t{0}) << "Must order using at least one index"; 53 DCHECK_LE(order.size(), shape.size()) << "Can only sort up to dims"; 54 for (size_t d = 0; d < order.size(); ++d) { 55 DCHECK_GE(order[d], 0); 56 DCHECK_LT(order[d], shape.size()); 57 } 58 } 59 operator()60 inline bool operator()(const int64 i, const int64 j) const { 61 for (int di = 0; di < dims_; ++di) { 62 const int64 d = order_[di]; 63 if (ix_(i, d) < ix_(j, d)) return true; 64 if (ix_(i, d) > ix_(j, d)) return false; 65 } 66 return false; 67 } 68 69 // Compares two indices taken from corresponding index matrices, using the 70 // standard, row-major (or lexicographic) order. Useful for cases that need 71 // to distinguish between all three orderings (<, ==, >). cmp(const TTypes<int64>::ConstMatrix & a_idx,const TTypes<int64>::ConstMatrix & b_idx,const int64 a_row,const int64 b_row,const int dims)72 inline static int cmp(const TTypes<int64>::ConstMatrix& a_idx, 73 const TTypes<int64>::ConstMatrix& b_idx, 74 const int64 a_row, const int64 b_row, const int dims) { 75 for (int d = 0; d < dims; ++d) { 76 const int64 a = a_idx(a_row, d); 77 const int64 b = b_idx(b_row, d); 78 if (a < b) { 79 return -1; 80 } else if (a > b) { 81 return 1; 82 } 83 } 84 return 0; 85 } 86 87 protected: 88 const TTypes<int64>::Matrix ix_; 89 const VarDimArray order_; 90 const int dims_; 91 const std::vector<int64>* ix_order_; 92 }; 93 94 template <int ORDER_DIM> 95 class FixedDimComparator : DimComparator { 96 public: FixedDimComparator(const TTypes<int64>::Matrix & ix,const VarDimArray & order,const VarDimArray & shape)97 FixedDimComparator(const TTypes<int64>::Matrix& ix, const VarDimArray& order, 98 const VarDimArray& shape) 99 : DimComparator(ix, order, shape) { 100 DCHECK_EQ(order.size(), ORDER_DIM); 101 } operator()102 inline bool operator()(const int64 i, const int64 j) const { 103 bool value = false; 104 for (int di = 0; di < ORDER_DIM; ++di) { 105 const int64 d = order_[di]; 106 if (ix_(i, d) < ix_(j, d)) { 107 value = true; 108 break; 109 } 110 if (ix_(i, d) > ix_(j, d)) break; 111 } 112 return value; 113 } 114 }; 115 116 } // namespace sparse 117 } // namespace tensorflow 118 119 #endif // TENSORFLOW_CORE_UTIL_SPARSE_DIM_COMPARATOR_H_ 120