5 #ifndef GKO_PUBLIC_CORE_BASE_MATRIX_DATA_HPP_
6 #define GKO_PUBLIC_CORE_BASE_MATRIX_DATA_HPP_
15 #include <ginkgo/core/base/dim.hpp>
16 #include <ginkgo/core/base/math.hpp>
17 #include <ginkgo/core/base/range.hpp>
18 #include <ginkgo/core/base/range_accessors.hpp>
19 #include <ginkgo/core/base/types.hpp>
20 #include <ginkgo/core/base/utils.hpp>
30 template <
typename ValueType,
typename IndexType>
38 template <
typename ValueType,
typename Distribution,
typename Generator>
39 typename std::enable_if<!is_complex_s<ValueType>::value, ValueType>::type
40 get_rand_value(Distribution&& dist, Generator&& gen)
46 template <
typename ValueType,
typename Distribution,
typename Generator>
47 typename std::enable_if<is_complex_s<ValueType>::value, ValueType>::type
48 get_rand_value(Distribution&& dist, Generator&& gen)
50 return ValueType(dist(gen), dist(gen));
60 template <
typename ValueType,
typename IndexType>
62 using value_type = ValueType;
63 using index_type = IndexType;
67 : row(r), column(c), value(v)
72 return std::tie(this->row, this->column, this->value) ==
73 std::tie(other.row, other.column, other.value);
77 return std::tie(this->row, this->column, this->value) !=
78 std::tie(other.row, other.column, other.value);
81 #define GKO_DEFINE_DEFAULT_COMPARE_OPERATOR(_op) \
82 bool operator _op(const matrix_data_entry& other) const \
84 return std::tie(this->row, this->column) \
85 _op std::tie(other.row, other.column); \
88 GKO_DEFINE_DEFAULT_COMPARE_OPERATOR(<);
89 GKO_DEFINE_DEFAULT_COMPARE_OPERATOR(>);
90 GKO_DEFINE_DEFAULT_COMPARE_OPERATOR(<=);
91 GKO_DEFINE_DEFAULT_COMPARE_OPERATOR(>=);
93 #undef GKO_DEFINE_DEFAULT_COMPARE_OPERATOR
95 friend std::ostream& operator<<(std::ostream& os,
98 os <<
'(' << x.row <<
',' << x.column <<
',' << x.value <<
')';
126 template <
typename ValueType = default_precision,
typename IndexType =
int32>
128 using value_type = ValueType;
129 using index_type = IndexType;
147 nonzeros.emplace_back(row, col, value);
162 template <
typename RandomDistribution,
typename RandomEngine>
170 detail::get_rand_value<ValueType>(dist, engine);
172 nonzeros.emplace_back(row, col, value);
183 matrix_data(std::initializer_list<std::initializer_list<ValueType>> values)
184 :
size{values.size(), 0}
186 for (
size_type row = 0; row < values.size(); ++row) {
187 const auto row_data = begin(values)[row];
188 size[1] = std::max(
size[1], row_data.size());
189 for (
size_type col = 0; col < row_data.size(); ++col) {
190 const auto& val = begin(row_data)[col];
192 nonzeros.emplace_back(row, col, val);
206 std::initializer_list<detail::input_triple<ValueType, IndexType>>
211 for (
const auto& elem : nonzeros_) {
212 nonzeros.emplace_back(elem.row, elem.col, elem.val);
225 nonzeros.reserve(size_[0] * size_[1] * block.nonzeros.size());
226 for (
size_type row = 0; row < size_[0]; ++row) {
227 for (
size_type col = 0; col < size_[1]; ++col) {
228 for (
const auto& elem : block.nonzeros) {
229 nonzeros.emplace_back(row * block.size[0] + elem.row,
230 col * block.size[1] + elem.column,
245 template <
typename Accessor>
252 nonzeros.emplace_back(row, col, data(row, col));
270 const auto num_nnz = std::min(size_[0], size_[1]);
272 for (
size_type i = 0; i < num_nnz; ++i) {
273 res.
nonzeros.emplace_back(i, i, value);
288 std::initializer_list<ValueType> nonzeros_)
291 res.
nonzeros.reserve(nonzeros_.size());
293 for (
auto value : nonzeros_) {
294 res.
nonzeros.emplace_back(pos, pos, value);
311 const auto num_blocks = std::min(size_[0], size_[1]);
313 for (
size_type b = 0; b < num_blocks; ++b) {
314 for (
const auto& elem : block.
nonzeros) {
316 b * block.
size[1] + elem.column,
334 template <
typename ForwardIterator>
339 return dim<2>{s[0] + d.size[0], s[1] + d.size[1]};
344 for (
auto it = begin; it != end; ++it) {
345 for (
const auto& elem : it->nonzeros) {
346 res.
nonzeros.emplace_back(row_offset + elem.row,
347 col_offset + elem.column, elem.value);
349 row_offset += it->size[0];
350 col_offset += it->size[1];
366 return diag(begin(blocks), end(blocks));
388 template <
typename RandomDistribution,
typename RandomEngine>
391 RandomDistribution&& dist, RandomEngine&& engine,
395 std::vector<ValueType> mtx_data(
size *
size, zero<ValueType>());
396 std::vector<ValueType> ref_data(
size);
397 std::vector<ValueType> work(
size);
399 range reflector(ref_data.data(),
size, 1u, 1u);
401 initialize_diag_with_cond(condition_number, matrix);
402 for (
size_type i = 0; i < num_reflectors; ++i) {
403 generate_random_reflector(dist, engine, reflector);
404 reflect_domain(reflector, matrix, work.data());
405 generate_random_reflector(dist, engine, reflector);
406 reflect_range(reflector, matrix, work.data());
432 template <
typename RandomDistribution,
typename RandomEngine>
435 RandomDistribution&& dist, RandomEngine&& engine)
438 std::forward<RandomDistribution>(dist),
439 std::forward<RandomEngine>(engine),
size - 1);
463 return std::tie(x.row, x.column) < std::tie(y.row, y.column);
493 std::vector<nonzero_type> new_nonzeros;
495 new_nonzeros.emplace_back(
nonzeros.front().row,
499 if (entry.row != new_nonzeros.back().row ||
500 entry.column != new_nonzeros.back().column) {
501 new_nonzeros.emplace_back(entry.row, entry.column,
504 new_nonzeros.back().value += entry.value;
511 template <
typename Accessor>
512 static void initialize_diag_with_cond(
518 const auto min_sigma =
one(condition_number) / sqrt(condition_number);
519 const auto max_sigma = sqrt(condition_number);
521 matrix =
zero(matrix);
523 matrix(i, i) = max_sigma * static_cast<sigma_type>(
size - i - 1) /
524 static_cast<sigma_type>(
size - 1) +
525 min_sigma * static_cast<sigma_type>(i) /
526 static_cast<sigma_type>(
size - 1);
530 template <
typename RandomDistribution,
typename RandomEngine,
532 static void generate_random_reflector(RandomDistribution&& dist,
533 RandomEngine&& engine,
534 const range<Accessor>& reflector)
537 reflector(i, 0) = detail::get_rand_value<ValueType>(dist, engine);
541 template <
typename Accessor>
542 static void reflect_domain(
const range<Accessor>& reflector,
543 const range<Accessor>& matrix,
544 ValueType* work_data)
546 const auto two = one<ValueType>() + one<ValueType>();
547 range<accessor::row_major<ValueType, 2>> work(work_data,
548 matrix.length(0), 1u, 1u);
549 work = mmul(matrix, reflector);
551 const auto scale = two / mmul(ct_reflector, reflector)(0, 0);
552 matrix = matrix - scale * mmul(work, ct_reflector);
555 template <
typename Accessor>
556 static void reflect_range(
const range<Accessor>& reflector,
557 const range<Accessor>& matrix,
558 ValueType* work_data)
560 const auto two = one<ValueType>() + one<ValueType>();
561 range<accessor::row_major<ValueType, 2>> work(
562 work_data, 1u, matrix.length(0), matrix.length(0));
564 work = mmul(ct_reflector, matrix);
565 const auto scale = two / mmul(ct_reflector, reflector)(0, 0);
566 matrix = matrix - scale * mmul(reflector, work);
574 #endif // GKO_PUBLIC_CORE_BASE_MATRIX_DATA_HPP_