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_t> VarDimArray; 48 DimComparator(const TTypes<int64_t>::Matrix & ix,const VarDimArray & order,const VarDimArray & shape)49 DimComparator(const TTypes<int64_t>::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_t i, const int64_t j) const { 61 for (int di = 0; di < dims_; ++di) { 62 const int64_t 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_t>::ConstMatrix & a_idx,const TTypes<int64_t>::ConstMatrix & b_idx,const int64_t a_row,const int64_t b_row,const int dims)72 inline static int cmp(const TTypes<int64_t>::ConstMatrix& a_idx, 73 const TTypes<int64_t>::ConstMatrix& b_idx, 74 const int64_t a_row, const int64_t b_row, 75 const int dims) { 76 for (int d = 0; d < dims; ++d) { 77 const int64_t a = a_idx(a_row, d); 78 const int64_t b = b_idx(b_row, d); 79 if (a < b) { 80 return -1; 81 } else if (a > b) { 82 return 1; 83 } 84 } 85 return 0; 86 } 87 88 protected: 89 const TTypes<int64_t>::Matrix ix_; 90 const VarDimArray order_; 91 const int dims_; 92 const std::vector<int64_t>* ix_order_; 93 }; 94 95 template <int ORDER_DIM> 96 class FixedDimComparator : DimComparator { 97 public: FixedDimComparator(const TTypes<int64_t>::Matrix & ix,const VarDimArray & order,const VarDimArray & shape)98 FixedDimComparator(const TTypes<int64_t>::Matrix& ix, 99 const VarDimArray& order, const VarDimArray& shape) 100 : DimComparator(ix, order, shape) { 101 DCHECK_EQ(order.size(), ORDER_DIM); 102 } operator()103 inline bool operator()(const int64_t i, const int64_t j) const { 104 bool value = false; 105 for (int di = 0; di < ORDER_DIM; ++di) { 106 const int64_t d = order_[di]; 107 if (ix_(i, d) < ix_(j, d)) { 108 value = true; 109 break; 110 } 111 if (ix_(i, d) > ix_(j, d)) break; 112 } 113 return value; 114 } 115 }; 116 117 } // namespace sparse 118 } // namespace tensorflow 119 120 #endif // TENSORFLOW_CORE_UTIL_SPARSE_DIM_COMPARATOR_H_ 121