This file is indexed.

/usr/include/TiledArray/math/gemm_helper.h is in libtiledarray-dev 0.6.0-5.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/*
 *  This file is a part of TiledArray.
 *  Copyright (C) 2014  Virginia Tech
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  Justus Calvin
 *  Department of Chemistry, Virginia Tech
 *
 *  gemm_helper.h
 *  Jan 20, 2014
 *
 */

#ifndef TILEDARRAY_MATH_GEMM_HELPER_H__INCLUDED
#define TILEDARRAY_MATH_GEMM_HELPER_H__INCLUDED

#include <TiledArray/error.h>
#include <TiledArray/madness.h>

namespace TiledArray {
  namespace math {

    /// Contraction to *GEMM helper

    /// This object is used to convert tensor contraction to *GEMM operations by
    /// providing information on how to fuse dimensions
    class GemmHelper {
    private:

      madness::cblas::CBLAS_TRANSPOSE left_op_;
              ///< Transpose operation that is applied to the left-hand argument
      madness::cblas::CBLAS_TRANSPOSE right_op_;
              ///< Transpose operation that is applied to the right-hand argument
      unsigned int result_rank_; ///< The rank of the result tensor

      /// Contraction argument range data

      /// The range data held by this object is the range of the inner and outer
      /// dimensions of the argument tensor. It is assumed that the inner and
      /// outer dimensions are contiguous.
      struct ContractArg {
        unsigned int inner[2]; ///< The inner dimension range
        unsigned int outer[2]; ///< The outer dimension range
        unsigned int rank; ///< Rank of the argument tensor
      }
        left_, ///< Left-hand argument range data
        right_; ///< Right-hand argument range data


    public:

      GemmHelper(const madness::cblas::CBLAS_TRANSPOSE left_op,
          const madness::cblas::CBLAS_TRANSPOSE right_op,
          const unsigned int result_rank, const unsigned int left_rank,
          const unsigned int right_rank) :
        left_op_(left_op), right_op_(right_op),
        result_rank_(result_rank), left_(), right_()
      {
        // Compute the number of contracted dimensions in left and right.
        TA_ASSERT(((left_rank + right_rank - result_rank) % 2u) == 0u);

        left_.rank = left_rank;
        right_.rank = right_rank;
        const unsigned int contract_size = num_contract_ranks();

        // Store the inner and outer dimension ranges for the left-hand argument.
        if(left_op == madness::cblas::NoTrans) {
          left_.outer[0] = 0u;
          left_.outer[1] = left_.inner[0] = left_rank - contract_size;
          left_.inner[1] = left_rank;
        } else {
          left_.inner[0] = 0ul;
          left_.inner[1] = left_.outer[0] = contract_size;
          left_.outer[1] = left_rank;
        }

        // Store the inner and outer dimension ranges for the right-hand argument.
        if(right_op == madness::cblas::NoTrans) {
          right_.inner[0] = 0u;
          right_.inner[1] = right_.outer[0] = contract_size;
          right_.outer[1] = right_rank;
        } else {
          right_.outer[0] = 0u;
          right_.outer[1] = right_.inner[0] = right_rank - contract_size;
          right_.inner[1] = right_rank;
        }
      }

      /// Functor copy constructor

      /// Shallow copy of this functor
      /// \param other The functor to be copied
      GemmHelper(const GemmHelper& other) :
        left_op_(other.left_op_), right_op_(other.right_op_),
        result_rank_(other.result_rank_),
        left_(other.left_), right_(other.right_)
      { }

      /// Functor assignment operator

      /// \param other The functor to be copied
      GemmHelper& operator=(const GemmHelper& other) {
        left_op_ = other.left_op_;
        right_op_ = other.right_op_;
        result_rank_ = other.result_rank_;
        left_ = other.left_;
        right_ = other.right_;

        return *this;
      }

      /// Compute the number of contracted ranks

      /// \return The number of ranks that are summed by this operation
      unsigned int num_contract_ranks() const {
        return (left_.rank + right_.rank - result_rank_) >> 1;
      }

      /// Result rank accessor

      /// \return The rank of the result tile
      unsigned int result_rank() const { return result_rank_; }

      /// Left-hand argument rank accessor

      /// \return The rank of the left-hand tile
      unsigned int left_rank() const { return left_.rank; }

      /// Right-hand argument rank accessor

      /// \return The rank of the right-hand tile
      unsigned int right_rank() const { return right_.rank; }

      unsigned int left_inner_begin() const { return left_.inner[0]; }
      unsigned int left_inner_end()   const { return left_.inner[1]; }
      unsigned int left_outer_begin() const { return left_.outer[0]; }
      unsigned int left_outer_end()   const { return left_.outer[1]; }

      unsigned int right_inner_begin() const { return right_.inner[0]; }
      unsigned int right_inner_end()   const { return right_.inner[1]; }
      unsigned int right_outer_begin() const { return right_.outer[0]; }
      unsigned int right_outer_end()   const { return right_.outer[1]; }

      /// Construct a result range based on \c left and \c right ranges

      /// \tparam R The result range type
      /// \tparam Left The left-hand range type
      /// \tparam Right The right-hand range type
      /// \param left The left-hand range
      /// \param right The right-hand range
      /// \return A range object that can be used in a tensor contraction
      /// defined by this object
      template <typename R, typename Left, typename Right>
      R make_result_range(const Left& left, const Right& right) const {
        // Get pointers to lower and upper bounds of left and right.
        const auto* restrict const left_lower = left.lobound_data();
        const auto* restrict const left_upper = left.upbound_data();
        const auto* restrict const right_lower = right.lobound_data();
        const auto* restrict const right_upper = right.upbound_data();

        // Create the start and finish indices
        std::vector<std::size_t> lower, upper;
        lower.reserve(result_rank_);
        upper.reserve(result_rank_);

        // Copy left-hand argument outer dimensions to start and finish
        for(unsigned int i = left_.outer[0]; i < left_.outer[1]; ++i) {
          lower.push_back(left_lower[i]);
          upper.push_back(left_upper[i]);
        }

        // Copy right-hand argument outer dimensions to start and finish
        for(unsigned int i = right_.outer[0]; i < right_.outer[1]; ++i) {
          lower.push_back(right_lower[i]);
          upper.push_back(right_upper[i]);
        }

        // Construct the result tile
        return R(lower, upper);
      }

      /// Test that the outer dimensions of left are coformal with that of the result tensor

      /// This function can test the start, finish, or size arrays of range
      /// objects.
      /// \tparam Left The left-hand size array type
      /// \tparam Result The result size array type
      /// \param left The left-hand size array to be tested
      /// \param result The result size array to be tested
      /// \return \c true if The outer dimensions of left are coformal with that
      /// of result
      template <typename Left, typename Result>
      bool left_result_coformal(const Left& left, const Result& result) const {
        return std::equal(left + left_.outer[0], left + left_.outer[1], result);
      }

      /// Test that the outer dimensions of right are coformal with that of the result tensor

      /// This function can test the start, finish, or size arrays of range
      /// objects.
      /// \tparam Right The right-hand size array type
      /// \tparam Result The result size array type
      /// \param right The right-hand size array to be tested
      /// \param result The result size array to be tested
      /// \return \c true if The outer dimensions of right are coformal with that
      /// of result
      template <typename Right, typename Result>
      bool right_result_coformal(const Right& right, const Result& result) const {
        return std::equal(right + right_.outer[0], right + right_.outer[1],
            result + (left_.outer[1] - left_.outer[0]));
      }

      /// Test that the inner dimensions of left are coformal with that of right

      /// This function can test the start, finish, or size arrays of range
      /// objects.
      /// \tparam Left The left-hand size array type
      /// \tparam Right The right-hand size array type
      /// \param left The left-hand size array to be tested
      /// \param right The right-hand size array to be tested
      /// \return \c true if the outer dimensions of \c left are coformal with
      /// that of \c right, other \c false.
      template <typename Left, typename Right>
      bool left_right_coformal(const Left& left, const Right& right) const {
        return std::equal(left + left_.inner[0], left + left_.inner[1],
            right + right_.inner[0]);
      }

      /// Compute the matrix dimension that can be used in a *GEMM call

      /// \tparam Left The left-hand range type
      /// \tparam Right The right-hand range type
      /// \param[out] m The number of rows in left-hand and result matrices
      /// \param[out] n The number of columns in the right-hand result matrices
      /// \param[out] k The number of columns in the left-hand matrix and the
      /// number of rows in the right-hand matrix
      /// \param[in] left The left-hand range object
      /// \param[in] right The right-hand range object
      template <typename Left, typename Right>
      void compute_matrix_sizes(integer& m, integer& n, integer& k,
          const Left& left, const Right& right) const
      {
        // Check that the arguments are not empty and have the correct ranks
        TA_ASSERT(left.rank() == left_.rank);
        TA_ASSERT(right.rank() == right_.rank);
        const auto* restrict const left_extent = left.extent_data();
        const auto* restrict const right_extent = right.extent_data();

        // Compute fused dimension sizes
        m = 1;
        for(unsigned int i = left_.outer[0]; i < left_.outer[1]; ++i)
          m *= left_extent[i];
        k = 1;
        for(unsigned int i = left_.inner[0]; i < left_.inner[1]; ++i)
          k *= left_extent[i];
        n = 1;
        for(unsigned int i = right_.outer[0]; i < right_.outer[1]; ++i)
          n *= right_extent[i];
      }

      madness::cblas::CBLAS_TRANSPOSE left_op() const { return left_op_; }
      madness::cblas::CBLAS_TRANSPOSE right_op() const { return right_op_; }
    }; // class GemmHelper

  }  // namespace math
} // namespace TiledArray

#endif // TILEDARRAY_MATH_GEMM_HELPER_H__INCLUDED