Ginkgo Generated from branch based on master. Ginkgo version 1.8.0
A numerical linear algebra library targeting many-core architectures
Loading...
Searching...
No Matches
hybrid.hpp
1// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#ifndef GKO_PUBLIC_CORE_MATRIX_HYBRID_HPP_
6#define GKO_PUBLIC_CORE_MATRIX_HYBRID_HPP_
7
8
9#include <algorithm>
10
11
12#include <ginkgo/core/base/array.hpp>
13#include <ginkgo/core/base/lin_op.hpp>
14#include <ginkgo/core/matrix/coo.hpp>
15#include <ginkgo/core/matrix/csr.hpp>
16#include <ginkgo/core/matrix/ell.hpp>
17
18
19namespace gko {
20namespace matrix {
21
22
23template <typename ValueType>
24class Dense;
25
26template <typename ValueType, typename IndexType>
27class Csr;
28
29
42template <typename ValueType = default_precision, typename IndexType = int32>
43class Hybrid
44 : public EnableLinOp<Hybrid<ValueType, IndexType>>,
45 public ConvertibleTo<Hybrid<next_precision<ValueType>, IndexType>>,
46 public ConvertibleTo<Dense<ValueType>>,
47 public ConvertibleTo<Csr<ValueType, IndexType>>,
48 public DiagonalExtractable<ValueType>,
49 public ReadableFromMatrixData<ValueType, IndexType>,
50 public WritableToMatrixData<ValueType, IndexType>,
52 remove_complex<Hybrid<ValueType, IndexType>>> {
54 friend class Dense<ValueType>;
55 friend class Csr<ValueType, IndexType>;
56 friend class Hybrid<to_complex<ValueType>, IndexType>;
57
58
59public:
60 using EnableLinOp<Hybrid>::convert_to;
61 using EnableLinOp<Hybrid>::move_to;
62 using ConvertibleTo<
63 Hybrid<next_precision<ValueType>, IndexType>>::convert_to;
64 using ConvertibleTo<Hybrid<next_precision<ValueType>, IndexType>>::move_to;
65 using ConvertibleTo<Dense<ValueType>>::convert_to;
66 using ConvertibleTo<Dense<ValueType>>::move_to;
69 using ReadableFromMatrixData<ValueType, IndexType>::read;
70
71 using value_type = ValueType;
72 using index_type = IndexType;
77 using absolute_type = remove_complex<Hybrid>;
78
79
90 public:
95 : ell_num_stored_elements_per_row_(zero<size_type>()),
96 coo_nnz_(zero<size_type>())
97 {}
98
112 size_type* ell_num_stored_elements_per_row,
113 size_type* coo_nnz)
114 {
115 array<size_type> ref_row_nnz(row_nnz.get_executor()->get_master(),
116 row_nnz.get_size());
117 ref_row_nnz = row_nnz;
118 ell_num_stored_elements_per_row_ =
119 this->compute_ell_num_stored_elements_per_row(&ref_row_nnz);
120 coo_nnz_ = this->compute_coo_nnz(ref_row_nnz);
121 *ell_num_stored_elements_per_row = ell_num_stored_elements_per_row_;
122 *coo_nnz = coo_nnz_;
123 }
124
131 {
132 return ell_num_stored_elements_per_row_;
133 }
134
140 size_type get_coo_nnz() const noexcept { return coo_nnz_; }
141
150 array<size_type>* row_nnz) const = 0;
151
152 protected:
161 size_type compute_coo_nnz(const array<size_type>& row_nnz) const
162 {
163 size_type coo_nnz = 0;
164 auto row_nnz_val = row_nnz.get_const_data();
165 for (size_type i = 0; i < row_nnz.get_size(); i++) {
166 if (row_nnz_val[i] > ell_num_stored_elements_per_row_) {
167 coo_nnz +=
168 row_nnz_val[i] - ell_num_stored_elements_per_row_;
169 }
170 }
171 return coo_nnz;
172 }
173
174 private:
175 size_type ell_num_stored_elements_per_row_;
176 size_type coo_nnz_;
177 };
178
184 public:
190 explicit column_limit(size_type num_column = 0)
191 : num_columns_(num_column)
192 {}
193
195 array<size_type>* row_nnz) const override
196 {
197 return num_columns_;
198 }
199
205 auto get_num_columns() const { return num_columns_; }
206
207 private:
208 size_type num_columns_;
209 };
210
219 public:
226 explicit imbalance_limit(double percent = 0.8) : percent_(percent)
227 {
228 percent_ = std::min(percent_, 1.0);
229 percent_ = std::max(percent_, 0.0);
230 }
231
233 array<size_type>* row_nnz) const override
234 {
235 auto row_nnz_val = row_nnz->get_data();
236 auto num_rows = row_nnz->get_size();
237 if (num_rows == 0) {
238 return 0;
239 }
240 std::sort(row_nnz_val, row_nnz_val + num_rows);
241 if (percent_ < 1) {
242 auto percent_pos = static_cast<size_type>(num_rows * percent_);
243 return row_nnz_val[percent_pos];
244 } else {
245 return row_nnz_val[num_rows - 1];
246 }
247 }
248
254 auto get_percentage() const { return percent_; }
255
256 private:
257 double percent_;
258 };
259
266 public:
270 imbalance_bounded_limit(double percent = 0.8, double ratio = 0.0001)
271 : strategy_(imbalance_limit(percent)), ratio_(ratio)
272 {}
273
275 array<size_type>* row_nnz) const override
276 {
277 auto num_rows = row_nnz->get_size();
278 auto ell_cols =
280 return std::min(ell_cols,
281 static_cast<size_type>(num_rows * ratio_));
282 }
283
289 auto get_percentage() const { return strategy_.get_percentage(); }
290
296 auto get_ratio() const { return ratio_; }
297
298 private:
299 imbalance_limit strategy_;
300 double ratio_;
301 };
302
303
310 public:
315 : strategy_(
316 imbalance_limit(static_cast<double>(sizeof(IndexType)) /
317 (sizeof(ValueType) + 2 * sizeof(IndexType))))
318 {}
319
321 array<size_type>* row_nnz) const override
322 {
323 return strategy_.compute_ell_num_stored_elements_per_row(row_nnz);
324 }
325
331 auto get_percentage() const { return strategy_.get_percentage(); }
332
333 private:
334 imbalance_limit strategy_;
335 };
336
337
342 class automatic : public strategy_type {
343 public:
347 automatic() : strategy_(imbalance_bounded_limit(1.0 / 3.0, 0.001)) {}
348
350 array<size_type>* row_nnz) const override
351 {
352 return strategy_.compute_ell_num_stored_elements_per_row(row_nnz);
353 }
354
355 private:
356 imbalance_bounded_limit strategy_;
357 };
358
359 friend class Hybrid<next_precision<ValueType>, IndexType>;
360
361 void convert_to(
362 Hybrid<next_precision<ValueType>, IndexType>* result) const override;
363
364 void move_to(Hybrid<next_precision<ValueType>, IndexType>* result) override;
365
366 void convert_to(Dense<ValueType>* other) const override;
367
368 void move_to(Dense<ValueType>* other) override;
369
370 void convert_to(Csr<ValueType, IndexType>* other) const override;
371
372 void move_to(Csr<ValueType, IndexType>* other) override;
373
374 void read(const mat_data& data) override;
375
376 void read(const device_mat_data& data) override;
377
378 void read(device_mat_data&& data) override;
379
380 void write(mat_data& data) const override;
381
382 std::unique_ptr<Diagonal<ValueType>> extract_diagonal() const override;
383
384 std::unique_ptr<absolute_type> compute_absolute() const override;
385
387
393 value_type* get_ell_values() noexcept { return ell_->get_values(); }
394
402 const value_type* get_const_ell_values() const noexcept
403 {
404 return ell_->get_const_values();
405 }
406
412 index_type* get_ell_col_idxs() noexcept { return ell_->get_col_idxs(); }
413
421 const index_type* get_const_ell_col_idxs() const noexcept
422 {
423 return ell_->get_const_col_idxs();
424 }
425
432 {
433 return ell_->get_num_stored_elements_per_row();
434 }
435
441 size_type get_ell_stride() const noexcept { return ell_->get_stride(); }
442
449 {
450 return ell_->get_num_stored_elements();
451 }
452
464 value_type& ell_val_at(size_type row, size_type idx) noexcept
465 {
466 return ell_->val_at(row, idx);
467 }
468
472 value_type ell_val_at(size_type row, size_type idx) const noexcept
473 {
474 return ell_->val_at(row, idx);
475 }
476
487 index_type& ell_col_at(size_type row, size_type idx) noexcept
488 {
489 return ell_->col_at(row, idx);
490 }
491
495 index_type ell_col_at(size_type row, size_type idx) const noexcept
496 {
497 return ell_->col_at(row, idx);
498 }
499
505 const ell_type* get_ell() const noexcept { return ell_.get(); }
506
512 value_type* get_coo_values() noexcept { return coo_->get_values(); }
513
521 const value_type* get_const_coo_values() const noexcept
522 {
523 return coo_->get_const_values();
524 }
525
531 index_type* get_coo_col_idxs() noexcept { return coo_->get_col_idxs(); }
532
540 const index_type* get_const_coo_col_idxs() const noexcept
541 {
542 return coo_->get_const_col_idxs();
543 }
544
550 index_type* get_coo_row_idxs() noexcept { return coo_->get_row_idxs(); }
551
559 const index_type* get_const_coo_row_idxs() const noexcept
560 {
561 return coo_->get_const_row_idxs();
562 }
563
570 {
571 return coo_->get_num_stored_elements();
572 }
573
579 const coo_type* get_coo() const noexcept { return coo_.get(); }
580
587 {
588 return coo_->get_num_stored_elements() +
589 ell_->get_num_stored_elements();
590 }
591
597 std::shared_ptr<strategy_type> get_strategy() const noexcept
598 {
599 return strategy_;
600 }
601
609 template <typename HybType>
610 std::shared_ptr<typename HybType::strategy_type> get_strategy() const;
611
622 static std::unique_ptr<Hybrid> create(
623 std::shared_ptr<const Executor> exec,
624 std::shared_ptr<strategy_type> strategy =
625 std::make_shared<automatic>());
626
638 static std::unique_ptr<Hybrid> create(
639 std::shared_ptr<const Executor> exec, const dim<2>& size,
640 std::shared_ptr<strategy_type> strategy =
641 std::make_shared<automatic>());
642
655 static std::unique_ptr<Hybrid> create(
656 std::shared_ptr<const Executor> exec, const dim<2>& size,
657 size_type num_stored_elements_per_row,
658 std::shared_ptr<strategy_type> strategy =
659 std::make_shared<automatic>());
660
673 static std::unique_ptr<Hybrid> create(
674 std::shared_ptr<const Executor> exec, const dim<2>& size,
675 size_type num_stored_elements_per_row, size_type stride,
676 std::shared_ptr<strategy_type> strategy);
677
691 static std::unique_ptr<Hybrid> create(
692 std::shared_ptr<const Executor> exec, const dim<2>& size,
693 size_type num_stored_elements_per_row, size_type stride,
694 size_type num_nonzeros = {},
695 std::shared_ptr<strategy_type> strategy =
696 std::make_shared<automatic>());
697
703
710
715 Hybrid(const Hybrid&);
716
723
724protected:
725 Hybrid(std::shared_ptr<const Executor> exec, const dim<2>& size = {},
726 size_type num_stored_elements_per_row = 0, size_type stride = 0,
727 size_type num_nonzeros = 0,
728 std::shared_ptr<strategy_type> strategy =
729 std::make_shared<automatic>());
730
741 void resize(dim<2> new_size, size_type ell_row_nnz, size_type coo_nnz);
742
743 void apply_impl(const LinOp* b, LinOp* x) const override;
744
745 void apply_impl(const LinOp* alpha, const LinOp* b, const LinOp* beta,
746 LinOp* x) const override;
747
748private:
749 std::unique_ptr<ell_type> ell_;
750 std::unique_ptr<coo_type> coo_;
751 std::shared_ptr<strategy_type> strategy_;
752};
753
754
755template <typename ValueType, typename IndexType>
756template <typename HybType>
757std::shared_ptr<typename HybType::strategy_type>
759{
760 static_assert(
761 std::is_same<HybType, Hybrid<typename HybType::value_type,
762 typename HybType::index_type>>::value,
763 "The given `HybType` type must be of type `matrix::Hybrid`!");
764
765 std::shared_ptr<typename HybType::strategy_type> strategy;
766 if (std::dynamic_pointer_cast<automatic>(strategy_)) {
767 strategy = std::make_shared<typename HybType::automatic>();
768 } else if (auto temp = std::dynamic_pointer_cast<minimal_storage_limit>(
769 strategy_)) {
770 // minimal_storage_limit is related to ValueType and IndexType size.
771 if (sizeof(value_type) == sizeof(typename HybType::value_type) &&
772 sizeof(index_type) == sizeof(typename HybType::index_type)) {
773 strategy =
774 std::make_shared<typename HybType::minimal_storage_limit>();
775 } else {
776 strategy = std::make_shared<typename HybType::imbalance_limit>(
777 temp->get_percentage());
778 }
779 } else if (auto temp = std::dynamic_pointer_cast<imbalance_bounded_limit>(
780 strategy_)) {
781 strategy = std::make_shared<typename HybType::imbalance_bounded_limit>(
782 temp->get_percentage(), temp->get_ratio());
783 } else if (auto temp =
784 std::dynamic_pointer_cast<imbalance_limit>(strategy_)) {
785 strategy = std::make_shared<typename HybType::imbalance_limit>(
786 temp->get_percentage());
787 } else if (auto temp = std::dynamic_pointer_cast<column_limit>(strategy_)) {
788 strategy = std::make_shared<typename HybType::column_limit>(
789 temp->get_num_columns());
790 } else {
791 GKO_NOT_SUPPORTED(strategy_);
792 }
793 return strategy;
794}
795
796
797} // namespace matrix
798} // namespace gko
799
800
801#endif // GKO_PUBLIC_CORE_MATRIX_HYBRID_HPP_
ConvertibleTo interface is used to mark that the implementer can be converted to the object of Result...
Definition polymorphic_object.hpp:471
The diagonal of a LinOp implementing this interface can be extracted.
Definition lin_op.hpp:744
The EnableAbsoluteComputation mixin provides the default implementations of compute_absolute_linop an...
Definition lin_op.hpp:795
The EnableLinOp mixin can be used to provide sensible default implementations of the majority of the ...
Definition lin_op.hpp:880
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition polymorphic_object.hpp:663
Definition lin_op.hpp:118
A LinOp implementing this interface can read its data from a matrix_data structure.
Definition lin_op.hpp:606
A LinOp implementing this interface can write its data to a matrix_data structure.
Definition lin_op.hpp:661
An array is a container which encapsulates fixed-sized arrays, stored on the Executor tied to the arr...
Definition logger.hpp:25
value_type * get_data() noexcept
Returns a pointer to the block of memory used to store the elements of the array.
Definition array.hpp:674
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor associated with the array.
Definition array.hpp:690
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:683
size_type get_size() const noexcept
Returns the number of elements in the array.
Definition array.hpp:657
This type is a device-side equivalent to matrix_data.
Definition device_matrix_data.hpp:36
COO stores a matrix in the coordinate matrix format.
Definition ell.hpp:21
CSR is a matrix format which stores only the nonzero coefficients by compressing each row of the matr...
Definition sparsity_csr.hpp:22
Dense is a matrix format which explicitly stores all values of the matrix.
Definition sparsity_csr.hpp:26
ELL is a matrix format where stride with explicit zeros is used such that all rows have the same numb...
Definition ell.hpp:60
automatic is a strategy_type which decides the number of stored elements per row of the ell part auto...
Definition hybrid.hpp:342
size_type compute_ell_num_stored_elements_per_row(array< size_type > *row_nnz) const override
Computes the number of stored elements per row of the ell part.
Definition hybrid.hpp:349
automatic()
Creates an automatic strategy.
Definition hybrid.hpp:347
column_limit is a strategy_type which decides the number of stored elements per row of the ell part b...
Definition hybrid.hpp:183
size_type compute_ell_num_stored_elements_per_row(array< size_type > *row_nnz) const override
Computes the number of stored elements per row of the ell part.
Definition hybrid.hpp:194
column_limit(size_type num_column=0)
Creates a column_limit strategy.
Definition hybrid.hpp:190
auto get_num_columns() const
Get the number of columns limit.
Definition hybrid.hpp:205
imbalance_bounded_limit is a strategy_type which decides the number of stored elements per row of the...
Definition hybrid.hpp:265
auto get_percentage() const
Get the percent setting.
Definition hybrid.hpp:289
size_type compute_ell_num_stored_elements_per_row(array< size_type > *row_nnz) const override
Computes the number of stored elements per row of the ell part.
Definition hybrid.hpp:274
imbalance_bounded_limit(double percent=0.8, double ratio=0.0001)
Creates a imbalance_bounded_limit strategy.
Definition hybrid.hpp:270
auto get_ratio() const
Get the ratio setting.
Definition hybrid.hpp:296
imbalance_limit is a strategy_type which decides the number of stored elements per row of the ell par...
Definition hybrid.hpp:218
size_type compute_ell_num_stored_elements_per_row(array< size_type > *row_nnz) const override
Computes the number of stored elements per row of the ell part.
Definition hybrid.hpp:232
auto get_percentage() const
Get the percent setting.
Definition hybrid.hpp:254
imbalance_limit(double percent=0.8)
Creates a imbalance_limit strategy.
Definition hybrid.hpp:226
minimal_storage_limit is a strategy_type which decides the number of stored elements per row of the e...
Definition hybrid.hpp:309
size_type compute_ell_num_stored_elements_per_row(array< size_type > *row_nnz) const override
Computes the number of stored elements per row of the ell part.
Definition hybrid.hpp:320
auto get_percentage() const
Get the percent setting.
Definition hybrid.hpp:331
minimal_storage_limit()
Creates a minimal_storage_limit strategy.
Definition hybrid.hpp:314
strategy_type is to decide how to set the hybrid config.
Definition hybrid.hpp:89
virtual size_type compute_ell_num_stored_elements_per_row(array< size_type > *row_nnz) const =0
Computes the number of stored elements per row of the ell part.
strategy_type()
Creates a strategy_type.
Definition hybrid.hpp:94
size_type get_ell_num_stored_elements_per_row() const noexcept
Returns the number of stored elements per row of the ell part.
Definition hybrid.hpp:130
void compute_hybrid_config(const array< size_type > &row_nnz, size_type *ell_num_stored_elements_per_row, size_type *coo_nnz)
Computes the config of the Hybrid matrix (ell_num_stored_elements_per_row and coo_nnz).
Definition hybrid.hpp:111
size_type get_coo_nnz() const noexcept
Returns the number of nonzeros of the coo part.
Definition hybrid.hpp:140
HYBRID is a matrix format which splits the matrix into ELLPACK and COO format.
Definition hybrid.hpp:52
size_type get_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the matrix.
Definition hybrid.hpp:586
static std::unique_ptr< Hybrid > create(std::shared_ptr< const Executor > exec, const dim< 2 > &size, size_type num_stored_elements_per_row, size_type stride, std::shared_ptr< strategy_type > strategy)
Creates an uninitialized Hybrid matrix of the specified size and method.
index_type * get_coo_row_idxs() noexcept
Returns the row indexes of the coo part.
Definition hybrid.hpp:550
value_type & ell_val_at(size_type row, size_type idx) noexcept
Returns the idx-th non-zero element of the row-th row in the ell part.
Definition hybrid.hpp:464
static std::unique_ptr< Hybrid > create(std::shared_ptr< const Executor > exec, const dim< 2 > &size, size_type num_stored_elements_per_row, std::shared_ptr< strategy_type > strategy=std::make_shared< automatic >())
Creates an uninitialized Hybrid matrix of the specified size and method.
size_type get_ell_stride() const noexcept
Returns the stride of the ell part.
Definition hybrid.hpp:441
size_type get_coo_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the coo part.
Definition hybrid.hpp:569
std::unique_ptr< absolute_type > compute_absolute() const override
Gets the AbsoluteLinOp.
index_type ell_col_at(size_type row, size_type idx) const noexcept
Returns the idx-th column index of the row-th row in the ell part.
Definition hybrid.hpp:495
index_type * get_coo_col_idxs() noexcept
Returns the column indexes of the coo part.
Definition hybrid.hpp:531
value_type ell_val_at(size_type row, size_type idx) const noexcept
Returns the idx-th non-zero element of the row-th row in the ell part.
Definition hybrid.hpp:472
const index_type * get_const_coo_row_idxs() const noexcept
Returns the row indexes of the coo part.
Definition hybrid.hpp:559
Hybrid(Hybrid &&)
Move-assigns a Hybrid matrix.
const value_type * get_const_ell_values() const noexcept
Returns the values of the ell part.
Definition hybrid.hpp:402
const ell_type * get_ell() const noexcept
Returns the matrix of the ell part.
Definition hybrid.hpp:505
std::unique_ptr< Diagonal< ValueType > > extract_diagonal() const override
Extracts the diagonal entries of the matrix into a vector.
value_type * get_ell_values() noexcept
Returns the values of the ell part.
Definition hybrid.hpp:393
static std::unique_ptr< Hybrid > create(std::shared_ptr< const Executor > exec, std::shared_ptr< strategy_type > strategy=std::make_shared< automatic >())
Creates an uninitialized Hybrid matrix of specified method.
size_type get_ell_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the ell part.
Definition hybrid.hpp:448
size_type get_ell_num_stored_elements_per_row() const noexcept
Returns the number of stored elements per row of ell part.
Definition hybrid.hpp:431
const index_type * get_const_coo_col_idxs() const noexcept
Returns the column indexes of the coo part.
Definition hybrid.hpp:540
Hybrid(const Hybrid &)
Copy-assigns a Hybrid matrix.
index_type * get_ell_col_idxs() noexcept
Returns the column indexes of the ell part.
Definition hybrid.hpp:412
void compute_absolute_inplace() override
Compute absolute inplace on each element.
const index_type * get_const_ell_col_idxs() const noexcept
Returns the column indexes of the ell part.
Definition hybrid.hpp:421
std::shared_ptr< strategy_type > get_strategy() const noexcept
Returns the strategy.
Definition hybrid.hpp:597
const coo_type * get_coo() const noexcept
Returns the matrix of the coo part.
Definition hybrid.hpp:579
static std::unique_ptr< Hybrid > create(std::shared_ptr< const Executor > exec, const dim< 2 > &size, size_type num_stored_elements_per_row, size_type stride, size_type num_nonzeros={}, std::shared_ptr< strategy_type > strategy=std::make_shared< automatic >())
Creates an uninitialized Hybrid matrix of the specified size and method.
value_type * get_coo_values() noexcept
Returns the values of the coo part.
Definition hybrid.hpp:512
static std::unique_ptr< Hybrid > create(std::shared_ptr< const Executor > exec, const dim< 2 > &size, std::shared_ptr< strategy_type > strategy=std::make_shared< automatic >())
Creates an uninitialized Hybrid matrix of the specified size and method.
Hybrid & operator=(const Hybrid &)
Copy-assigns a Hybrid matrix.
index_type & ell_col_at(size_type row, size_type idx) noexcept
Returns the idx-th column index of the row-th row in the ell part.
Definition hybrid.hpp:487
const value_type * get_const_coo_values() const noexcept
Returns the values of the coo part.
Definition hybrid.hpp:521
Hybrid & operator=(Hybrid &&)
Move-assigns a Hybrid matrix.
The Ginkgo namespace.
Definition abstract_factory.hpp:20
typename detail::remove_complex_s< T >::type remove_complex
Obtain the type which removed the complex of complex/scalar type or the template parameter of class b...
Definition math.hpp:326
typename detail::next_precision_impl< T >::type next_precision
Obtains the next type in the singly-linked precision list.
Definition math.hpp:462
typename detail::to_complex_s< T >::type to_complex
Obtain the type which adds the complex of complex/scalar type or the template parameter of class by a...
Definition math.hpp:345
constexpr T zero()
Returns the additive identity for T.
Definition math.hpp:747
std::size_t size_type
Integral type used for allocation quantities.
Definition types.hpp:86
A type representing the dimensions of a multidimensional object.
Definition dim.hpp:27
This structure is used as an intermediate data type to store a sparse matrix.
Definition matrix_data.hpp:127