5 #ifndef GKO_PUBLIC_CORE_BASE_MATRIX_DATA_HPP_
6 #define GKO_PUBLIC_CORE_BASE_MATRIX_DATA_HPP_
14 #include <ginkgo/core/base/dim.hpp>
15 #include <ginkgo/core/base/math.hpp>
16 #include <ginkgo/core/base/range.hpp>
17 #include <ginkgo/core/base/range_accessors.hpp>
18 #include <ginkgo/core/base/types.hpp>
19 #include <ginkgo/core/base/utils.hpp>
29 template <
typename ValueType,
typename IndexType>
37 template <
typename ValueType,
typename Distribution,
typename Generator>
38 typename std::enable_if<!is_complex_s<ValueType>::value, ValueType>::type
39 get_rand_value(Distribution&& dist, Generator&& gen)
45 template <
typename ValueType,
typename Distribution,
typename Generator>
46 typename std::enable_if<is_complex_s<ValueType>::value, ValueType>::type
47 get_rand_value(Distribution&& dist, Generator&& gen)
49 return ValueType(dist(gen), dist(gen));
59 template <
typename ValueType,
typename IndexType>
61 using value_type = ValueType;
62 using index_type = IndexType;
66 : row(r), column(c), value(v)
71 return std::tie(this->row, this->column, this->value) ==
72 std::tie(other.row, other.column, other.value);
76 return std::tie(this->row, this->column, this->value) !=
77 std::tie(other.row, other.column, other.value);
80 #define GKO_DEFINE_DEFAULT_COMPARE_OPERATOR(_op) \
81 bool operator _op(const matrix_data_entry& other) const \
83 return std::tie(this->row, this->column) \
84 _op std::tie(other.row, other.column); \
87 GKO_DEFINE_DEFAULT_COMPARE_OPERATOR(<);
88 GKO_DEFINE_DEFAULT_COMPARE_OPERATOR(>);
89 GKO_DEFINE_DEFAULT_COMPARE_OPERATOR(<=);
90 GKO_DEFINE_DEFAULT_COMPARE_OPERATOR(>=);
92 #undef GKO_DEFINE_DEFAULT_COMPARE_OPERATOR
94 friend std::ostream& operator<<(std::ostream& os,
97 os <<
'(' << x.row <<
',' << x.column <<
',' << x.value <<
')';
125 template <
typename ValueType = default_precision,
typename IndexType =
int32>
127 using value_type = ValueType;
128 using index_type = IndexType;
146 nonzeros.emplace_back(row, col, value);
161 template <
typename RandomDistribution,
typename RandomEngine>
169 detail::get_rand_value<ValueType>(dist, engine);
171 nonzeros.emplace_back(row, col, value);
182 matrix_data(std::initializer_list<std::initializer_list<ValueType>> values)
183 :
size{values.size(), 0}
185 for (
size_type row = 0; row < values.size(); ++row) {
186 const auto row_data = begin(values)[row];
187 size[1] = std::max(
size[1], row_data.size());
188 for (
size_type col = 0; col < row_data.size(); ++col) {
189 const auto& val = begin(row_data)[col];
191 nonzeros.emplace_back(row, col, val);
205 std::initializer_list<detail::input_triple<ValueType, IndexType>>
210 for (
const auto& elem : nonzeros_) {
211 nonzeros.emplace_back(elem.row, elem.col, elem.val);
224 nonzeros.reserve(size_[0] * size_[1] * block.nonzeros.size());
225 for (
size_type row = 0; row < size_[0]; ++row) {
226 for (
size_type col = 0; col < size_[1]; ++col) {
227 for (
const auto& elem : block.nonzeros) {
228 nonzeros.emplace_back(row * block.size[0] + elem.row,
229 col * block.size[1] + elem.column,
244 template <
typename Accessor>
251 nonzeros.emplace_back(row, col, data(row, col));
269 const auto num_nnz = std::min(size_[0], size_[1]);
271 for (
size_type i = 0; i < num_nnz; ++i) {
272 res.
nonzeros.emplace_back(i, i, value);
287 std::initializer_list<ValueType> nonzeros_)
290 res.
nonzeros.reserve(nonzeros_.size());
292 for (
auto value : nonzeros_) {
293 res.
nonzeros.emplace_back(pos, pos, value);
310 const auto num_blocks = std::min(size_[0], size_[1]);
312 for (
size_type b = 0; b < num_blocks; ++b) {
313 for (
const auto& elem : block.
nonzeros) {
315 b * block.
size[1] + elem.column,
333 template <
typename ForwardIterator>
338 return dim<2>{s[0] + d.size[0], s[1] + d.size[1]};
343 for (
auto it = begin; it != end; ++it) {
344 for (
const auto& elem : it->nonzeros) {
345 res.
nonzeros.emplace_back(row_offset + elem.row,
346 col_offset + elem.column, elem.value);
348 row_offset += it->size[0];
349 col_offset += it->size[1];
365 return diag(begin(blocks), end(blocks));
387 template <
typename RandomDistribution,
typename RandomEngine>
390 RandomDistribution&& dist, RandomEngine&& engine,
394 std::vector<ValueType> mtx_data(
size *
size, zero<ValueType>());
395 std::vector<ValueType> ref_data(
size);
396 std::vector<ValueType> work(
size);
398 range reflector(ref_data.data(),
size, 1u, 1u);
400 initialize_diag_with_cond(condition_number, matrix);
401 for (
size_type i = 0; i < num_reflectors; ++i) {
402 generate_random_reflector(dist, engine, reflector);
403 reflect_domain(reflector, matrix, work.data());
404 generate_random_reflector(dist, engine, reflector);
405 reflect_range(reflector, matrix, work.data());
431 template <
typename RandomDistribution,
typename RandomEngine>
434 RandomDistribution&& dist, RandomEngine&& engine)
437 std::forward<RandomDistribution>(dist),
438 std::forward<RandomEngine>(engine),
size - 1);
462 return std::tie(x.row, x.column) < std::tie(y.row, y.column);
492 std::vector<nonzero_type> new_nonzeros;
494 new_nonzeros.emplace_back(
nonzeros.front().row,
498 if (entry.row != new_nonzeros.back().row ||
499 entry.column != new_nonzeros.back().column) {
500 new_nonzeros.emplace_back(entry.row, entry.column,
503 new_nonzeros.back().value += entry.value;
510 template <
typename Accessor>
511 static void initialize_diag_with_cond(
517 const auto min_sigma =
one(condition_number) / sqrt(condition_number);
518 const auto max_sigma = sqrt(condition_number);
520 matrix =
zero(matrix);
522 matrix(i, i) = max_sigma * static_cast<sigma_type>(
size - i - 1) /
523 static_cast<sigma_type>(
size - 1) +
524 min_sigma * static_cast<sigma_type>(i) /
525 static_cast<sigma_type>(
size - 1);
529 template <
typename RandomDistribution,
typename RandomEngine,
531 static void generate_random_reflector(RandomDistribution&& dist,
532 RandomEngine&& engine,
533 const range<Accessor>& reflector)
536 reflector(i, 0) = detail::get_rand_value<ValueType>(dist, engine);
540 template <
typename Accessor>
541 static void reflect_domain(
const range<Accessor>& reflector,
542 const range<Accessor>& matrix,
543 ValueType* work_data)
545 const auto two = one<ValueType>() + one<ValueType>();
546 range<accessor::row_major<ValueType, 2>> work(work_data,
547 matrix.length(0), 1u, 1u);
548 work = mmul(matrix, reflector);
550 const auto scale = two / mmul(ct_reflector, reflector)(0, 0);
551 matrix = matrix - scale * mmul(work, ct_reflector);
554 template <
typename Accessor>
555 static void reflect_range(
const range<Accessor>& reflector,
556 const range<Accessor>& matrix,
557 ValueType* work_data)
559 const auto two = one<ValueType>() + one<ValueType>();
560 range<accessor::row_major<ValueType, 2>> work(
561 work_data, 1u, matrix.length(0), matrix.length(0));
563 work = mmul(ct_reflector, matrix);
564 const auto scale = two / mmul(ct_reflector, reflector)(0, 0);
565 matrix = matrix - scale * mmul(reflector, work);
573 #endif // GKO_PUBLIC_CORE_BASE_MATRIX_DATA_HPP_