Ginkgo  Generated from tags/v1.0.0^0 branch based on master. Ginkgo version 1.0.0
A numerical linear algebra library targeting many-core architectures
dense.hpp
1 /*******************************<GINKGO LICENSE>******************************
2 Copyright (c) 2017-2019, the Ginkgo authors
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 
16 3. Neither the name of the copyright holder nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 ******************************<GINKGO LICENSE>*******************************/
32 
33 #ifndef GKO_CORE_MATRIX_DENSE_HPP_
34 #define GKO_CORE_MATRIX_DENSE_HPP_
35 
36 
37 #include <ginkgo/core/base/array.hpp>
38 #include <ginkgo/core/base/executor.hpp>
39 #include <ginkgo/core/base/lin_op.hpp>
40 #include <ginkgo/core/base/mtx_io.hpp>
41 #include <ginkgo/core/base/range_accessors.hpp>
42 #include <ginkgo/core/base/types.hpp>
43 #include <ginkgo/core/base/utils.hpp>
44 
45 
46 #include <initializer_list>
47 
48 
49 namespace gko {
50 namespace matrix {
51 
52 
53 template <typename ValueType, typename IndexType>
54 class Coo;
55 
56 template <typename ValueType, typename IndexType>
57 class Csr;
58 
59 template <typename ValueType, typename IndexType>
60 class Ell;
61 
62 template <typename ValueType, typename IndexType>
63 class Hybrid;
64 
65 template <typename ValueType, typename IndexType>
66 class Sellp;
67 
68 
84 template <typename ValueType = default_precision>
85 class Dense : public EnableLinOp<Dense<ValueType>>,
86  public EnableCreateMethod<Dense<ValueType>>,
87  public ConvertibleTo<Coo<ValueType, int32>>,
88  public ConvertibleTo<Coo<ValueType, int64>>,
89  public ConvertibleTo<Csr<ValueType, int32>>,
90  public ConvertibleTo<Csr<ValueType, int64>>,
91  public ConvertibleTo<Ell<ValueType, int32>>,
92  public ConvertibleTo<Ell<ValueType, int64>>,
93  public ConvertibleTo<Hybrid<ValueType, int32>>,
94  public ConvertibleTo<Hybrid<ValueType, int64>>,
95  public ConvertibleTo<Sellp<ValueType, int32>>,
96  public ConvertibleTo<Sellp<ValueType, int64>>,
97  public ReadableFromMatrixData<ValueType, int32>,
98  public ReadableFromMatrixData<ValueType, int64>,
99  public WritableToMatrixData<ValueType, int32>,
100  public WritableToMatrixData<ValueType, int64>,
101  public Transposable {
102  friend class EnableCreateMethod<Dense>;
103  friend class EnablePolymorphicObject<Dense, LinOp>;
104  friend class Coo<ValueType, int32>;
105  friend class Coo<ValueType, int64>;
106  friend class Csr<ValueType, int32>;
107  friend class Csr<ValueType, int64>;
108  friend class Ell<ValueType, int32>;
109  friend class Ell<ValueType, int64>;
110  friend class Hybrid<ValueType, int32>;
111  friend class Hybrid<ValueType, int64>;
112  friend class Sellp<ValueType, int32>;
113  friend class Sellp<ValueType, int64>;
114 
115 public:
118 
119  using value_type = ValueType;
120  using index_type = int64;
122  using mat_data32 = gko::matrix_data<ValueType, int32>;
123 
124  using row_major_range = gko::range<gko::accessor::row_major<ValueType, 2>>;
125 
131  static std::unique_ptr<Dense> create_with_config_of(const Dense *other)
132  {
133  // De-referencing `other` before calling the functions (instead of
134  // using operator `->`) is currently required to be compatible with
135  // CUDA 10.1.
136  // Otherwise, it results in a compile error.
137  // TODO Check if the compiler error is fixed and revert to `operator->`.
138  return Dense::create((*other).get_executor(), (*other).get_size(),
139  (*other).get_stride());
140  }
141 
142  void convert_to(Coo<ValueType, int32> *result) const override;
143 
144  void move_to(Coo<ValueType, int32> *result) override;
145 
146  void convert_to(Coo<ValueType, int64> *result) const override;
147 
148  void move_to(Coo<ValueType, int64> *result) override;
149 
150  void convert_to(Csr<ValueType, int32> *result) const override;
151 
152  void move_to(Csr<ValueType, int32> *result) override;
153 
154  void convert_to(Csr<ValueType, int64> *result) const override;
155 
156  void move_to(Csr<ValueType, int64> *result) override;
157 
158  void convert_to(Ell<ValueType, int32> *result) const override;
159 
160  void move_to(Ell<ValueType, int32> *result) override;
161 
162  void convert_to(Ell<ValueType, int64> *result) const override;
163 
164  void move_to(Ell<ValueType, int64> *result) override;
165 
166  void convert_to(Hybrid<ValueType, int32> *result) const override;
167 
168  void move_to(Hybrid<ValueType, int32> *result) override;
169 
170  void convert_to(Hybrid<ValueType, int64> *result) const override;
171 
172  void move_to(Hybrid<ValueType, int64> *result) override;
173 
174  void convert_to(Sellp<ValueType, int32> *result) const override;
175 
176  void move_to(Sellp<ValueType, int32> *result) override;
177 
178  void convert_to(Sellp<ValueType, int64> *result) const override;
179 
180  void move_to(Sellp<ValueType, int64> *result) override;
181 
182  void read(const mat_data &data) override;
183 
184  void read(const mat_data32 &data) override;
185 
186  void write(mat_data &data) const override;
187 
188  void write(mat_data32 &data) const override;
189 
190  std::unique_ptr<LinOp> transpose() const override;
191 
192  std::unique_ptr<LinOp> conj_transpose() const override;
193 
199  value_type *get_values() noexcept { return values_.get_data(); }
200 
208  const value_type *get_const_values() const noexcept
209  {
210  return values_.get_const_data();
211  }
212 
218  size_type get_stride() const noexcept { return stride_; }
219 
226  {
227  return values_.get_num_elems();
228  }
229 
240  value_type &at(size_type row, size_type col) noexcept
241  {
242  return values_.get_data()[linearize_index(row, col)];
243  }
244 
248  value_type at(size_type row, size_type col) const noexcept
249  {
250  return values_.get_const_data()[linearize_index(row, col)];
251  }
252 
267  ValueType &at(size_type idx) noexcept
268  {
269  return values_.get_data()[linearize_index(idx)];
270  }
271 
275  ValueType at(size_type idx) const noexcept
276  {
277  return values_.get_const_data()[linearize_index(idx)];
278  }
279 
289  void scale(const LinOp *alpha)
290  {
291  auto exec = this->get_executor();
292  this->scale_impl(make_temporary_clone(exec, alpha).get());
293  }
294 
305  void add_scaled(const LinOp *alpha, const LinOp *b)
306  {
307  auto exec = this->get_executor();
308  this->add_scaled_impl(make_temporary_clone(exec, alpha).get(),
309  make_temporary_clone(exec, b).get());
310  }
311 
321  void compute_dot(const LinOp *b, LinOp *result) const
322  {
323  auto exec = this->get_executor();
324  this->compute_dot_impl(make_temporary_clone(exec, b).get(),
325  make_temporary_clone(exec, result).get());
326  }
327 
335  void compute_norm2(LinOp *result) const
336  {
337  auto exec = this->get_executor();
338  this->compute_norm2_impl(make_temporary_clone(exec, result).get());
339  }
340 
351  std::unique_ptr<Dense> create_submatrix(const span &rows,
352  const span &columns,
353  const size_type stride)
354  {
355  row_major_range range_this{this->get_values(), this->get_size()[0],
356  this->get_size()[1], this->get_stride()};
357  auto range_result = range_this(rows, columns);
358  // TODO: can result in HUGE padding - which will be copied with the
359  // vector
360  return Dense::create(
361  this->get_executor(),
362  dim<2>{range_result.length(0), range_result.length(1)},
364  this->get_executor(),
365  range_result.length(0) * range_this.length(1) - columns.begin,
366  range_result->data),
367  stride);
368  }
369 
370  /*
371  * Create a submatrix from the original matrix.
372  *
373  * @param rows row span
374  * @param columns column span
375  */
376  std::unique_ptr<Dense> create_submatrix(const span &rows,
377  const span &columns)
378  {
379  return create_submatrix(rows, columns, this->get_stride());
380  }
381 
382 protected:
389  Dense(std::shared_ptr<const Executor> exec, const dim<2> &size = dim<2>{})
390  : Dense(std::move(exec), size, size[1])
391  {}
392 
402  Dense(std::shared_ptr<const Executor> exec, const dim<2> &size,
403  size_type stride)
404  : EnableLinOp<Dense>(exec, size),
405  values_(exec, size[0] * stride),
406  stride_(stride)
407  {}
408 
425  template <typename ValuesArray>
426  Dense(std::shared_ptr<const Executor> exec, const dim<2> &size,
427  ValuesArray &&values, size_type stride)
428  : EnableLinOp<Dense>(exec, size),
429  values_{exec, std::forward<ValuesArray>(values)},
430  stride_{stride}
431  {
432  GKO_ENSURE_IN_BOUNDS((size[0] - 1) * stride + size[1] - 1,
433  values_.get_num_elems());
434  }
435 
442  virtual void scale_impl(const LinOp *alpha);
443 
450  virtual void add_scaled_impl(const LinOp *alpha, const LinOp *b);
451 
458  virtual void compute_dot_impl(const LinOp *b, LinOp *result) const;
459 
466  virtual void compute_norm2_impl(LinOp *result) const;
467 
468  void apply_impl(const LinOp *b, LinOp *x) const override;
469 
470  void apply_impl(const LinOp *alpha, const LinOp *b, const LinOp *beta,
471  LinOp *x) const override;
472 
473  size_type linearize_index(size_type row, size_type col) const noexcept
474  {
475  return row * stride_ + col;
476  }
477 
478  size_type linearize_index(size_type idx) const noexcept
479  {
480  return linearize_index(idx / this->get_size()[1],
481  idx % this->get_size()[1]);
482  }
483 
484 private:
485  Array<value_type> values_;
486  size_type stride_;
487 }; // namespace matrix
488 
489 
490 } // namespace matrix
491 
492 
514 template <typename Matrix, typename... TArgs>
515 std::unique_ptr<Matrix> initialize(
516  size_type stride, std::initializer_list<typename Matrix::value_type> vals,
517  std::shared_ptr<const Executor> exec, TArgs &&... create_args)
518 {
520  size_type num_rows = vals.size();
521  auto tmp = dense::create(exec->get_master(), dim<2>{num_rows, 1}, stride);
522  size_type idx = 0;
523  for (const auto &elem : vals) {
524  tmp->at(idx) = elem;
525  ++idx;
526  }
527  auto mtx = Matrix::create(exec, std::forward<TArgs>(create_args)...);
528  tmp->move_to(mtx.get());
529  return mtx;
530 }
531 
553 template <typename Matrix, typename... TArgs>
554 std::unique_ptr<Matrix> initialize(
555  std::initializer_list<typename Matrix::value_type> vals,
556  std::shared_ptr<const Executor> exec, TArgs &&... create_args)
557 {
558  return initialize<Matrix>(1, vals, std::move(exec),
559  std::forward<TArgs>(create_args)...);
560 }
561 
562 
584 template <typename Matrix, typename... TArgs>
585 std::unique_ptr<Matrix> initialize(
586  size_type stride,
587  std::initializer_list<std::initializer_list<typename Matrix::value_type>>
588  vals,
589  std::shared_ptr<const Executor> exec, TArgs &&... create_args)
590 {
592  size_type num_rows = vals.size();
593  size_type num_cols = num_rows > 0 ? begin(vals)->size() : 1;
594  auto tmp =
595  dense::create(exec->get_master(), dim<2>{num_rows, num_cols}, stride);
596  size_type ridx = 0;
597  for (const auto &row : vals) {
598  size_type cidx = 0;
599  for (const auto &elem : row) {
600  tmp->at(ridx, cidx) = elem;
601  ++cidx;
602  }
603  ++ridx;
604  }
605  auto mtx = Matrix::create(exec, std::forward<TArgs>(create_args)...);
606  tmp->move_to(mtx.get());
607  return mtx;
608 }
609 
610 
633 template <typename Matrix, typename... TArgs>
634 std::unique_ptr<Matrix> initialize(
635  std::initializer_list<std::initializer_list<typename Matrix::value_type>>
636  vals,
637  std::shared_ptr<const Executor> exec, TArgs &&... create_args)
638 {
639  return initialize<Matrix>(vals.size() > 0 ? begin(vals)->size() : 0, vals,
640  std::move(exec),
641  std::forward<TArgs>(create_args)...);
642 }
643 
644 
645 } // namespace gko
646 
647 
648 #endif // GKO_CORE_MATRIX_DENSE_HPP_
value_type & at(size_type row, size_type col) noexcept
Returns a single element of the matrix.
Definition: dense.hpp:240
size_type get_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the matrix.
Definition: dense.hpp:225
This mixin implements a static create() method on ConcreteType that dynamically allocates the memory...
Definition: polymorphic_object.hpp:576
size_type get_num_elems() const noexcept
Returns the number of elements in the Array.
Definition: array.hpp:388
ELL is a matrix format where stride with explicit zeros is used such that all rows have the same numb...
Definition: csr.hpp:53
ConvertibleTo interface is used to mark that the implementer can be converted to the object of Result...
Definition: polymorphic_object.hpp:380
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition: polymorphic_object.hpp:505
std::int32_t int32
32-bit signed integral type.
Definition: types.hpp:111
std::unique_ptr< LinOp > conj_transpose() const override
Returns a LinOp representing the conjugate transpose of the Transposable object.
std::size_t size_type
Integral type used for allocation quantities.
Definition: types.hpp:94
void compute_norm2(LinOp *result) const
Computes the Euclidian (L^2) norm of this matrix.
Definition: dense.hpp:335
const value_type * get_const_values() const noexcept
Returns a pointer to the array of values of the matrix.
Definition: dense.hpp:208
const value_type * get_const_data() const noexcept
Returns a constant pointer to the block of memory used to store the elements of the Array...
Definition: array.hpp:406
The Ginkgo namespace.
Definition: abstract_factory.hpp:45
CSR is a matrix format which stores only the nonzero coefficients by compressing each row of the matr...
Definition: coo.hpp:51
ValueType & at(size_type idx) noexcept
Returns a single element of the matrix.
Definition: dense.hpp:267
void add_scaled(const LinOp *alpha, const LinOp *b)
Adds b scaled by alpha to the matrix (aka: BLAS axpy).
Definition: dense.hpp:305
SELL-P is a matrix format similar to ELL format.
Definition: csr.hpp:57
Dense is a matrix format which explicitly stores all values of the matrix.
Definition: coo.hpp:55
Definition: lin_op.hpp:134
The EnableLinOp mixin can be used to provide sensible default implementations of the majority of the ...
Definition: lin_op.hpp:509
const dim< 2 > & get_size() const noexcept
Returns the size of the operator.
Definition: lin_op.hpp:221
COO stores a matrix in the coordinate matrix format.
Definition: coo.hpp:73
std::int64_t int64
64-bit signed integral type.
Definition: types.hpp:117
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor of the object.
Definition: polymorphic_object.hpp:201
std::unique_ptr< Matrix > initialize(size_type stride, std::initializer_list< typename Matrix::value_type > vals, std::shared_ptr< const Executor > exec, TArgs &&... create_args)
Creates and initializes a column-vector.
Definition: dense.hpp:515
static std::unique_ptr< Dense > create_with_config_of(const Dense *other)
Creates a Dense matrix with the configuration of another Dense matrix.
Definition: dense.hpp:131
void scale(const LinOp *alpha)
Scales the matrix with a scalar (aka: BLAS scal).
Definition: dense.hpp:289
std::unique_ptr< LinOp > transpose() const override
Returns a LinOp representing the transpose of the Transposable object.
void compute_dot(const LinOp *b, LinOp *result) const
Computes the column-wise dot product of this matrix and b.
Definition: dense.hpp:321
A LinOp implementing this interface can write its data to a matrix_data structure.
Definition: lin_op.hpp:446
ValueType at(size_type idx) const noexcept
Returns a single element of the matrix.
Definition: dense.hpp:275
size_type get_stride() const noexcept
Returns the stride of the matrix.
Definition: dense.hpp:218
const size_type begin
Beginning of the span.
Definition: range.hpp:105
std::unique_ptr< Dense > create_submatrix(const span &rows, const span &columns, const size_type stride)
Create a submatrix from the original matrix.
Definition: dense.hpp:351
value_type * get_data() noexcept
Returns a pointer to the block of memory used to store the elements of the Array. ...
Definition: array.hpp:397
Linear operators which support transposition should implement the Transposable interface.
Definition: lin_op.hpp:398
This structure is used as an intermediate data type to store a sparse matrix.
Definition: matrix_data.hpp:102
A span is a lightweight structure used to create sub-ranges from other ranges.
Definition: range.hpp:73
A LinOp implementing this interface can read its data from a matrix_data structure.
Definition: lin_op.hpp:426
A range is a multidimensional view of the memory.
Definition: range.hpp:296
HYBRID is a matrix format which splits the matrix into ELLPACK and COO format.
Definition: dense.hpp:63
value_type at(size_type row, size_type col) const noexcept
Returns a single element of the matrix.
Definition: dense.hpp:248
temporary_clone< T > make_temporary_clone(std::shared_ptr< const Executor > exec, T *ptr)
Creates a temporary_clone.
Definition: utils.hpp:474
static Array view(std::shared_ptr< const Executor > exec, size_type num_elems, value_type *data)
Creates an Array from existing memory.
Definition: array.hpp:266
value_type * get_values() noexcept
Returns a pointer to the array of values of the matrix.
Definition: dense.hpp:199