Home | History | Annotate | Download | only in sparse
      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_UTIL_SPARSE_DIM_COMPARATOR_H_
     17 #define TENSORFLOW_UTIL_SPARSE_DIM_COMPARATOR_H_
     18 
     19 #include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
     20 #include "tensorflow/core/kernels/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 
     49   DimComparator(const TTypes<int64>::Matrix& ix, const VarDimArray& order,
     50                 const VarDimArray& shape)
     51       : ix_(ix), order_(order), dims_(shape.size()) {
     52     CHECK_GT(order.size(), size_t{0}) << "Must order using at least one index";
     53     CHECK_LE(order.size(), shape.size()) << "Can only sort up to dims";
     54     for (size_t d = 0; d < order.size(); ++d) {
     55       CHECK_GE(order[d], 0);
     56       CHECK_LT(order[d], shape.size());
     57     }
     58   }
     59 
     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 (<, ==, >).
     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:
     97   FixedDimComparator(const TTypes<int64>::Matrix& ix, const VarDimArray& order,
     98                      const VarDimArray& shape)
     99       : DimComparator(ix, order, shape) {
    100     CHECK_EQ(order.size(), ORDER_DIM);
    101   }
    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_UTIL_SPARSE_DIM_COMPARATOR_H_
    120