suanPan
Loading...
Searching...
No Matches
triplet_form.hpp
Go to the documentation of this file.
1/*******************************************************************************
2 * Copyright (C) 2017-2025 Theodore Chang
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
17
18#ifndef TRIPLET_FORM_HPP
19#define TRIPLET_FORM_HPP
20
21#include <Toolbox/utility.h>
22#include <numeric>
23
24template<sp_d data_t, sp_i index_t> class csc_form;
25template<sp_d data_t, sp_i index_t> class csr_form;
26
27enum class SparseBase : short unsigned {
28 ZERO,
29 ONE
30};
31
32template<sp_i index_t> class csr_comparator {
33 const index_t* const row_idx;
34 const index_t* const col_idx;
35
36public:
37 csr_comparator(const index_t* const in_row_idx, const index_t* const in_col_idx)
38 : row_idx(in_row_idx)
39 , col_idx(in_col_idx) {}
40
41 bool operator()(const index_t idx_a, const index_t idx_b) const {
42 if(row_idx[idx_a] == row_idx[idx_b]) return col_idx[idx_a] < col_idx[idx_b];
43 return row_idx[idx_a] < row_idx[idx_b];
44 }
45};
46
47template<sp_i index_t> class csc_comparator {
48 const index_t* const row_idx;
49 const index_t* const col_idx;
50
51public:
52 csc_comparator(const index_t* const in_row_idx, const index_t* const in_col_idx)
53 : row_idx(in_row_idx)
54 , col_idx(in_col_idx) {}
55
56 bool operator()(const index_t idx_a, const index_t idx_b) const {
57 if(col_idx[idx_a] == col_idx[idx_b]) return row_idx[idx_a] < row_idx[idx_b];
58 return col_idx[idx_a] < col_idx[idx_b];
59 }
60};
61
62template<sp_d data_t, sp_i index_t> class triplet_form final {
63 const data_t bin = data_t(0);
64
65 using index_ptr = std::unique_ptr<index_t[]>;
66 using data_ptr = std::unique_ptr<data_t[]>;
67
68 index_ptr row_idx = nullptr; // index storage
69 index_ptr col_idx = nullptr; // index storage
70 data_ptr val_idx = nullptr; // value storage
71
72 bool csc_sorted = false;
73 bool csr_sorted = false;
74
75 template<sp_d in_dt, sp_i in_it> void copy_to(const std::unique_ptr<in_it[]>& new_row_idx, const std::unique_ptr<in_it[]>& new_col_idx, const std::unique_ptr<in_dt[]>& new_val_idx, const index_t begin, const index_t row_offset, const index_t col_offset, const data_t scalar) const { copy_to(new_row_idx.get(), new_col_idx.get(), new_val_idx.get(), begin, row_offset, col_offset, scalar); }
76
77 template<sp_d in_dt, sp_i in_it> void copy_to(in_it* const new_row_idx, in_it* const new_col_idx, in_dt* const new_val_idx, const index_t begin, const index_t row_offset, const index_t col_offset, const data_t scalar) const {
78 suanpan::for_each(n_elem, [&](const index_t I) {
79 new_row_idx[I + begin] = in_it(row_idx[I] + row_offset);
80 new_col_idx[I + begin] = in_it(col_idx[I] + col_offset);
81 new_val_idx[I + begin] = in_dt(scalar * val_idx[I]);
82 });
83 }
84
88 void reserve(const index_t in_elem) {
89 if(in_elem <= n_alloc) return;
90
91 access::rw(n_alloc) = index_t(std::pow(2., std::ceil(std::log2(in_elem)) + 1));
92
93 index_ptr new_row_idx(new index_t[n_alloc]);
94 index_ptr new_col_idx(new index_t[n_alloc]);
95 data_ptr new_val_idx(new data_t[n_alloc]);
96
97 copy_to(new_row_idx, new_col_idx, new_val_idx, 0, 0, 0, 1);
98
99 row_idx = std::move(new_row_idx);
100 col_idx = std::move(new_col_idx);
101 val_idx = std::move(new_val_idx);
102 }
103
104 void invalidate_sorting_flag() { csc_sorted = csr_sorted = false; }
105
106 void condense(bool = false);
107
108 void populate_diagonal() {
109 const auto t_elem = std::min(n_rows, n_cols);
110 reserve(n_elem + t_elem);
111 suanpan::for_each(t_elem, [&](const index_t I) {
112 row_idx[n_elem + I] = I;
113 col_idx[n_elem + I] = I;
114 val_idx[n_elem + I] = data_t(0);
115 });
116 access::rw(n_elem) += t_elem;
117 invalidate_sorting_flag();
118 }
119
120public:
121 using data_type = data_t;
122 using index_type = index_t;
123
124 template<sp_d in_dt, sp_i in_it> friend class csc_form;
125 template<sp_d in_dt, sp_i in_it> friend class csr_form;
126 template<sp_d in_dt, sp_i in_it> friend class triplet_form;
127
128 const index_t n_rows = 0;
129 const index_t n_cols = 0;
130 const index_t n_elem = 0;
131 const index_t n_alloc = 0;
132
133 triplet_form() = default;
136 triplet_form& operator=(const triplet_form&);
137 triplet_form& operator=(triplet_form&&) noexcept;
138 ~triplet_form() = default;
139
140 triplet_form(const index_t in_rows, const index_t in_cols, const index_t in_elem = index_t(0))
141 : n_rows(in_rows)
142 , n_cols(in_cols) { init(in_elem); }
143
144 template<sp_d in_dt> explicit triplet_form(const SpMat<in_dt>&);
145 template<sp_d in_dt, sp_i in_it> explicit triplet_form(triplet_form<in_dt, in_it>&, SparseBase = SparseBase::ZERO, bool = false);
146
147 template<sp_d in_dt, sp_i in_it> explicit triplet_form(triplet_form<in_dt, in_it>&& in_mat, const SparseBase in_base = SparseBase::ZERO, const bool in_full = false)
148 : triplet_form(in_mat, in_base, in_full) {}
149
150 [[nodiscard]] const index_t* row_mem() const { return row_idx.get(); }
151
152 [[nodiscard]] const index_t* col_mem() const { return col_idx.get(); }
153
154 [[nodiscard]] const data_t* val_mem() const { return val_idx.get(); }
155
156 [[nodiscard]] index_t* row_mem() { return row_idx.get(); }
157
158 [[nodiscard]] index_t* col_mem() { return col_idx.get(); }
159
160 [[nodiscard]] data_t* val_mem() { return val_idx.get(); }
161
162 [[nodiscard]] index_t row(const index_t I) const { return row_idx[I]; }
163
164 [[nodiscard]] index_t col(const index_t I) const { return col_idx[I]; }
165
166 [[nodiscard]] data_t val(const index_t I) const { return val_idx[I]; }
167
168 [[nodiscard]] bool is_csr_sorted() const { return csr_sorted; }
169
170 [[nodiscard]] bool is_csc_sorted() const { return csc_sorted; }
171
172 [[nodiscard]] bool is_empty() const { return 0 == n_elem; }
173
174 [[nodiscard]] data_t max() const {
175 if(is_empty()) return data_t(0);
176 return *suanpan::max_element(val_idx.get(), val_idx.get() + n_elem);
177 }
178
179 void zeros() {
180 access::rw(n_elem) = 0;
181 invalidate_sorting_flag();
182 }
183
184 void init(const index_t in_elem) {
185 zeros();
186 reserve(in_elem);
187 }
188
189 void init(const index_t in_rows, const index_t in_cols, const index_t in_elem) {
190 access::rw(n_rows) = in_rows;
191 access::rw(n_cols) = in_cols;
192 init(in_elem);
193 }
194
195 data_t operator()(const index_t row, const index_t col) const {
196 for(index_t I = 0; I < n_elem; ++I) if(row == row_idx[I] && col == col_idx[I]) return val_idx[I];
197 return access::rw(bin) = 0.;
198 }
199
200 data_t& at(index_t, index_t);
201
214 void hack_size(const index_t in_elem) {
215 reserve(in_elem);
216 access::rw(n_elem) = in_elem;
217 }
218
219 void print() const;
220
221 void save(std::string_view) const;
222
223 void csr_sort();
224 void csc_sort();
225
227 csr_sort();
228 condense(false);
229 }
230
232 csc_sort();
233 condense(false);
234 }
235
237 populate_diagonal();
238 csr_sort();
239 condense(true);
240 }
241
243 populate_diagonal();
244 csc_sort();
245 condense(true);
246 }
247
248 void assemble(const Mat<data_t>&, const Col<uword>&);
249 template<sp_d in_dt, sp_i in_it> void assemble(const triplet_form<in_dt, in_it>&, index_t, index_t, data_t);
250
251 template<sp_d in_dt, sp_i in_it> void assemble(const triplet_form<in_dt, in_it>& in_mat, const std::vector<index_t>& row_shift, const std::vector<index_t>& col_shift, const std::vector<data_t>& scalar) {
252 suanpan_assert([&] { if(scalar.size() != row_shift.size() || scalar.size() != col_shift.size()) throw invalid_argument("size mismatch detected"); });
253
254 reserve(n_elem + index_t(scalar.size()) * index_t(in_mat.n_elem));
255
256 for(size_t I = 0; I < scalar.size(); ++I) assemble(in_mat, row_shift[I], col_shift[I], scalar[I]);
257 }
258
259 Mat<data_t> operator*(const Col<data_t>& in_mat) const {
260 Mat<data_t> out_mat(in_mat.n_rows, in_mat.n_cols, fill::zeros);
261
262 for(index_t I = 0; I < n_elem; ++I) out_mat(row_idx[I]) += val_idx[I] * in_mat(col_idx[I]);
263
264 return out_mat;
265 }
266
267 Mat<data_t> operator*(const Mat<data_t>& in_mat) const {
268 Mat<data_t> out_mat(in_mat.n_rows, in_mat.n_cols, fill::zeros);
269
270 for(index_t I = 0; I < n_elem; ++I) out_mat.row(row_idx[I]) += val_idx[I] * in_mat.row(col_idx[I]);
271
272 return out_mat;
273 }
274
275 template<sp_d T2> triplet_form operator*(T2) const;
276 template<sp_d T2> triplet_form operator/(T2) const;
277 template<sp_d T2> triplet_form& operator*=(T2);
278 template<sp_d T2> triplet_form& operator/=(T2);
279
280 triplet_form operator+(const triplet_form& in_mat) const {
281 triplet_form copy = *this;
282 // ReSharper disable once CppDFAUnusedValue
283 return copy += in_mat;
284 }
285
286 triplet_form operator-(const triplet_form& in_mat) const {
287 triplet_form copy = *this;
288 // ReSharper disable once CppDFAUnusedValue
289 return copy -= in_mat;
290 }
291
294
295 [[nodiscard]] Col<data_t> diag() const;
296 [[nodiscard]] triplet_form diagonal() const;
297 [[nodiscard]] triplet_form strictly_upper() const;
298 [[nodiscard]] triplet_form strictly_lower() const;
299 [[nodiscard]] triplet_form upper() const;
300 [[nodiscard]] triplet_form lower() const;
301};
302
303template<sp_d data_t, sp_i index_t> void triplet_form<data_t, index_t>::condense(const bool full) {
304 if(n_elem < 2) return;
305
306 auto last_row = row_idx[0], last_col = col_idx[0];
307
308 sp_i auto current_pos = index_t(0);
309 sp_d auto last_sum = data_t(0);
310
311 auto populate = [&] {
312 if(suanpan::approx_equal(last_sum, data_t(0)) && (!full || last_row != last_col)) return;
313 row_idx[current_pos] = last_row;
314 col_idx[current_pos] = last_col;
315 val_idx[current_pos] = last_sum;
316 ++current_pos;
317 last_sum = data_t(0);
318 };
319
320 for(index_t I = 0; I < n_elem; ++I) {
321 if(last_row != row_idx[I] || last_col != col_idx[I]) {
322 populate();
323 last_row = row_idx[I];
324 last_col = col_idx[I];
325 }
326 last_sum += val_idx[I];
327 }
328
329 populate();
330
331 access::rw(n_elem) = current_pos;
332}
333
334template<sp_d data_t, sp_i index_t> triplet_form<data_t, index_t>::triplet_form(const triplet_form& in_mat)
335 : csc_sorted{in_mat.csc_sorted}
336 , csr_sorted{in_mat.csr_sorted}
337 , n_rows{in_mat.n_rows}
338 , n_cols{in_mat.n_cols} {
339 init(in_mat.n_alloc);
340 in_mat.copy_to(row_idx, col_idx, val_idx, 0, 0, 0, 1);
341 access::rw(n_elem) = in_mat.n_elem;
342}
343
344template<sp_d data_t, sp_i index_t> triplet_form<data_t, index_t>::triplet_form(triplet_form&& in_mat) noexcept
345 : row_idx{std::move(in_mat.row_idx)}
346 , col_idx{std::move(in_mat.col_idx)}
347 , val_idx{std::move(in_mat.val_idx)}
348 , csc_sorted{in_mat.csc_sorted}
349 , csr_sorted{in_mat.csr_sorted}
350 , n_rows{in_mat.n_rows}
351 , n_cols{in_mat.n_cols}
352 , n_elem{in_mat.n_elem}
353 , n_alloc{in_mat.n_alloc} {}
354
356 if(this == &in_mat) return *this;
357 csc_sorted = in_mat.csc_sorted;
358 csr_sorted = in_mat.csr_sorted;
359 access::rw(n_rows) = in_mat.n_rows;
360 access::rw(n_cols) = in_mat.n_cols;
361 init(in_mat.n_alloc);
362 in_mat.copy_to(row_idx, col_idx, val_idx, 0, 0, 0, 1);
363 access::rw(n_elem) = in_mat.n_elem;
364 return *this;
365}
366
367template<sp_d data_t, sp_i index_t> triplet_form<data_t, index_t>& triplet_form<data_t, index_t>::operator=(triplet_form&& in_mat) noexcept {
368 if(this == &in_mat) return *this;
369 csc_sorted = in_mat.csc_sorted;
370 csr_sorted = in_mat.csr_sorted;
371 access::rw(n_rows) = in_mat.n_rows;
372 access::rw(n_cols) = in_mat.n_cols;
373 access::rw(n_elem) = in_mat.n_elem;
374 access::rw(n_alloc) = in_mat.n_alloc;
375 row_idx = std::move(in_mat.row_idx);
376 col_idx = std::move(in_mat.col_idx);
377 val_idx = std::move(in_mat.val_idx);
378 return *this;
379}
380
381template<sp_d data_t, sp_i index_t> template<sp_d in_dt> triplet_form<data_t, index_t>::triplet_form(const SpMat<in_dt>& in_mat)
382 : n_rows(index_t(in_mat.n_rows))
383 , n_cols(index_t(in_mat.n_cols)) {
384 init(index_t(in_mat.n_nonzero));
385
386 for(auto I = in_mat.begin(); I != in_mat.end(); ++I) at(I.row(), I.col()) = *I;
387}
388
389template<sp_d data_t, sp_i index_t> template<sp_d in_dt, sp_i in_it> triplet_form<data_t, index_t>::triplet_form(triplet_form<in_dt, in_it>& in_mat, const SparseBase base, const bool full)
390 : csc_sorted(in_mat.csc_sorted)
391 , csr_sorted(in_mat.csr_sorted)
392 , n_rows(index_t(in_mat.n_rows))
393 , n_cols(index_t(in_mat.n_cols)) {
394 if(in_mat.is_empty()) return;
395
396 init(index_t(in_mat.n_alloc));
397
398 if(full) in_mat.full_csc_condense();
399 else in_mat.csc_condense();
400
401 const sp_i auto shift = index_t(base);
402
403 in_mat.copy_to(row_idx, col_idx, val_idx, 0, shift, shift, 1);
404
405 access::rw(n_elem) = index_t(in_mat.n_elem);
406}
407
408template<sp_d data_t, sp_i index_t> data_t& triplet_form<data_t, index_t>::at(const index_t row, const index_t col) {
409 suanpan_assert([&] { if(row >= n_rows || col >= n_cols) throw invalid_argument("inconsistent size"); });
410
411 invalidate_sorting_flag();
412 reserve(n_elem + 1);
413 row_idx[n_elem] = row;
414 col_idx[n_elem] = col;
415 return val_idx[access::rw(n_elem)++] = data_t(0);
416}
417
418template<sp_d data_t, sp_i index_t> void triplet_form<data_t, index_t>::print() const {
419 suanpan_info("A sparse matrix in triplet form with size of {} by {}, the density of {:.3f}%.\n", n_rows, n_cols, static_cast<double>(n_elem) / static_cast<double>(n_rows) / static_cast<double>(n_cols) * 1E2);
420 if(n_elem > index_t(1000)) {
421 suanpan_info("More than 1000 elements exist.\n");
422 return;
423 }
424 for(index_t I = 0; I < n_elem; ++I)
425 suanpan_info("({}, {}) ===> {:+.8E}\n", row_idx[I], col_idx[I], val_idx[I]);
426}
427
444template<sp_d data_t, sp_i index_t> void triplet_form<data_t, index_t>::save(const std::string_view file_name) const {
445 std::ofstream file(file_name.data());
446 if(!file.is_open()) return;
447 file << suanpan::format("{} {} {}\n", n_rows, n_cols, n_elem);
448 for(index_t I = 0; I < n_elem; ++I) file << suanpan::format("{} {} {}\n", row_idx[I], col_idx[I], val_idx[I]);
449 file.close();
450}
451
465template<sp_d data_t, sp_i index_t> void triplet_form<data_t, index_t>::csr_sort() {
466 if(csr_sorted) return;
467
468 std::vector<index_t> index(n_elem);
469 std::iota(index.begin(), index.end(), index_t(0));
470
471 suanpan_sort(index.begin(), index.end(), csr_comparator<index_t>(row_idx.get(), col_idx.get()));
472
473 index_ptr new_row_idx(new index_t[n_alloc]);
474 index_ptr new_col_idx(new index_t[n_alloc]);
475 data_ptr new_val_idx(new data_t[n_alloc]);
476
477 suanpan::for_each(n_elem, [&](const index_t I) {
478 new_row_idx[I] = row_idx[index[I]];
479 new_col_idx[I] = col_idx[index[I]];
480 new_val_idx[I] = val_idx[index[I]];
481 });
482
483 row_idx = std::move(new_row_idx);
484 col_idx = std::move(new_col_idx);
485 val_idx = std::move(new_val_idx);
486
487 csr_sorted = true;
488 csc_sorted = false;
489}
490
504template<sp_d data_t, sp_i index_t> void triplet_form<data_t, index_t>::csc_sort() {
505 if(csc_sorted) return;
506
507 std::vector<index_t> index(n_elem);
508 std::iota(index.begin(), index.end(), index_t(0));
509
510 suanpan_sort(index.begin(), index.end(), csc_comparator<index_t>(row_idx.get(), col_idx.get()));
511
512 index_ptr new_row_idx(new index_t[n_alloc]);
513 index_ptr new_col_idx(new index_t[n_alloc]);
514 data_ptr new_val_idx(new data_t[n_alloc]);
515
516 suanpan::for_each(n_elem, [&](const index_t I) {
517 new_row_idx[I] = row_idx[index[I]];
518 new_col_idx[I] = col_idx[index[I]];
519 new_val_idx[I] = val_idx[index[I]];
520 });
521
522 row_idx = std::move(new_row_idx);
523 col_idx = std::move(new_col_idx);
524 val_idx = std::move(new_val_idx);
525
526 csc_sorted = true;
527 csr_sorted = false;
528}
529
530template<sp_d data_t, sp_i index_t> void triplet_form<data_t, index_t>::assemble(const Mat<data_t>& in_mat, const Col<uword>& in_dof) {
531 if(in_mat.empty()) return;
532
533 invalidate_sorting_flag();
534
535 const auto t_elem = n_elem + index_t(in_mat.n_elem);
536
537 reserve(t_elem);
538
539 suanpan::for_each(in_mat.n_elem, [&](const uword I) {
540 row_idx[n_elem + I] = index_t(in_dof(I % in_dof.n_elem));
541 col_idx[n_elem + I] = index_t(in_dof(I / in_dof.n_elem));
542 val_idx[n_elem + I] = in_mat(I);
543 });
544
545 access::rw(n_elem) = t_elem;
546}
547
548template<sp_d data_t, sp_i index_t> template<sp_d in_dt, sp_i in_it> void triplet_form<data_t, index_t>::assemble(const triplet_form<in_dt, in_it>& in_mat, const index_t row_shift, const index_t col_shift, const data_t scalar) {
549 if(in_mat.is_empty()) return;
550
551 invalidate_sorting_flag();
552
553 const auto t_elem = n_elem + in_mat.n_elem;
554
555 reserve(t_elem);
556
557 in_mat.copy_to(row_idx, col_idx, val_idx, n_elem, row_shift, col_shift, scalar);
558
559 access::rw(n_elem) = t_elem;
560}
561
562template<sp_d data_t, sp_i index_t> template<sp_d T2> triplet_form<data_t, index_t> triplet_form<data_t, index_t>::operator*(const T2 scalar) const {
563 if(suanpan::approx_equal(T2(0), scalar)) return triplet_form(n_rows, n_cols);
564
565 auto copy = *this;
566
567 if(suanpan::approx_equal(T2(1), scalar)) return copy;
568
569 if(suanpan::approx_equal(T2(-1), scalar))
570 suanpan_for_each(copy.val_idx.get(), copy.val_idx.get() + copy.n_elem, [](data_t& I) { I = -I; });
571 else
572 suanpan_for_each(copy.val_idx.get(), copy.val_idx.get() + copy.n_elem, [=](data_t& I) { I *= data_t(scalar); });
573
574 return copy;
575}
576
577template<sp_d data_t, sp_i index_t> template<sp_d T2> triplet_form<data_t, index_t> triplet_form<data_t, index_t>::operator/(const T2 scalar) const {
578 auto copy = *this;
579
580 if(suanpan::approx_equal(T2(1), scalar)) return copy;
581
582 if(suanpan::approx_equal(T2(-1), scalar))
583 suanpan_for_each(copy.val_idx.get(), copy.val_idx.get() + copy.n_elem, [](data_t& I) { I = -I; });
584 else
585 suanpan_for_each(copy.val_idx.get(), copy.val_idx.get() + copy.n_elem, [=](data_t& I) { I /= data_t(scalar); });
586
587 return copy;
588}
589
590template<sp_d data_t, sp_i index_t> template<sp_d T2> triplet_form<data_t, index_t>& triplet_form<data_t, index_t>::operator*=(const T2 scalar) {
591 if(suanpan::approx_equal(T2(1), scalar)) return *this;
592
593 if(suanpan::approx_equal(T2(0), scalar)) zeros();
594 else if(suanpan::approx_equal(T2(-1), scalar))
595 suanpan_for_each(val_idx.get(), val_idx.get() + n_elem, [](data_t& I) { I = -I; });
596 else
597 suanpan_for_each(val_idx.get(), val_idx.get() + n_elem, [=](data_t& I) { I *= data_t(scalar); });
598
599 return *this;
600}
601
602template<sp_d data_t, sp_i index_t> template<sp_d T2> triplet_form<data_t, index_t>& triplet_form<data_t, index_t>::operator/=(const T2 scalar) {
603 if(suanpan::approx_equal(T2(1), scalar)) return *this;
604
605 if(suanpan::approx_equal(T2(-1), scalar))
606 suanpan_for_each(val_idx.get(), val_idx.get() + n_elem, [](data_t& I) { I = -I; });
607 else
608 suanpan_for_each(val_idx.get(), val_idx.get() + n_elem, [=](data_t& I) { I /= data_t(scalar); });
609
610 return *this;
611}
612
614 if(in_mat.is_empty()) return *this;
615
616 invalidate_sorting_flag();
617
618 const auto t_elem = n_elem + index_t(in_mat.n_elem);
619
620 reserve(t_elem);
621
622 in_mat.copy_to(row_idx, col_idx, val_idx, n_elem, 0, 0, 1);
623
624 access::rw(n_elem) = t_elem;
625
626 return *this;
627}
628
630 if(in_mat.is_empty()) return *this;
631
632 invalidate_sorting_flag();
633
634 const auto t_elem = n_elem + index_t(in_mat.n_elem);
635
636 reserve(t_elem);
637
638 in_mat.copy_to(row_idx, col_idx, val_idx, n_elem, 0, 0, -1);
639
640 access::rw(n_elem) = t_elem;
641
642 return *this;
643}
644
645template<sp_d data_t, sp_i index_t> Col<data_t> triplet_form<data_t, index_t>::diag() const {
646 Col<data_t> diag_vec(std::min(n_rows, n_cols), fill::zeros);
647 for(index_t I = 0; I < n_elem; ++I)
648 if(row(I) == col(I)) diag_vec(row(I)) += val(I);
649 return diag_vec;
650}
651
653 auto out_mat = *this;
654
655 suanpan::for_each(out_mat.n_elem, [&](const index_t I) { out_mat.val_idx[I] *= out_mat.row(I) == out_mat.col(I); });
656
657 return out_mat;
658}
659
661 auto out_mat = *this;
662
663 suanpan::for_each(out_mat.n_elem, [&](const index_t I) { out_mat.val_idx[I] *= out_mat.row(I) < out_mat.col(I); });
664
665 return out_mat;
666}
667
669 auto out_mat = *this;
670
671 suanpan::for_each(out_mat.n_elem, [&](const index_t I) { out_mat.val_idx[I] *= out_mat.col(I) < out_mat.row(I); });
672
673 return out_mat;
674}
675
676template<sp_d data_t, sp_i index_t> triplet_form<data_t, index_t> triplet_form<data_t, index_t>::upper() const {
677 auto out_mat = *this;
678
679 suanpan::for_each(out_mat.n_elem, [&](const index_t I) { out_mat.val_idx[I] *= out_mat.row(I) <= out_mat.col(I); });
680
681 return out_mat;
682}
683
684template<sp_d data_t, sp_i index_t> triplet_form<data_t, index_t> triplet_form<data_t, index_t>::lower() const {
685 auto out_mat = *this;
686
687 suanpan::for_each(out_mat.n_elem, [&](const index_t I) { out_mat.val_idx[I] *= out_mat.col(I) <= out_mat.row(I); });
688
689 return out_mat;
690}
691
692template<sp_d data_t, sp_i index_t> triplet_form<data_t, index_t> operator+(const triplet_form<data_t, index_t>& mat_a, const triplet_form<data_t, index_t>& mat_b) {
693 auto out = mat_a;
694 out += mat_b;
695 return out;
696}
697
699 mat_a += mat_b;
700 return std::move(mat_a);
701}
702
704 mat_b += mat_a;
705 return std::move(mat_b);
706}
707
709 mat_a += mat_b;
710 return std::move(mat_a);
711}
712
713#endif
Storage< T >::iterator begin(Storage< T > &S)
Definition Storage.hpp:200
Definition triplet_form.hpp:47
bool operator()(const index_t idx_a, const index_t idx_b) const
Definition triplet_form.hpp:56
csc_comparator(const index_t *const in_row_idx, const index_t *const in_col_idx)
Definition triplet_form.hpp:52
Definition csc_form.hpp:25
Definition triplet_form.hpp:32
bool operator()(const index_t idx_a, const index_t idx_b) const
Definition triplet_form.hpp:41
csr_comparator(const index_t *const in_row_idx, const index_t *const in_col_idx)
Definition triplet_form.hpp:37
Definition csr_form.hpp:25
Definition triplet_form.hpp:62
void csr_sort()
Sorts the COO format into the CSR (Compressed Sparse Row) order.
Definition triplet_form.hpp:465
data_t data_type
Definition triplet_form.hpp:121
triplet_form strictly_lower() const
Definition triplet_form.hpp:668
triplet_form operator+(const triplet_form &in_mat) const
Definition triplet_form.hpp:280
void zeros()
Definition triplet_form.hpp:179
data_t * val_mem()
Definition triplet_form.hpp:160
void assemble(const triplet_form< in_dt, in_it > &, index_t, index_t, data_t)
Definition triplet_form.hpp:548
triplet_form()=default
triplet_form(triplet_form< in_dt, in_it > &&in_mat, const SparseBase in_base=SparseBase::ZERO, const bool in_full=false)
Definition triplet_form.hpp:147
const index_t n_rows
Definition triplet_form.hpp:128
triplet_form upper() const
Definition triplet_form.hpp:676
void save(std::string_view) const
Saves the triplet form matrix to a file.
Definition triplet_form.hpp:444
const index_t n_alloc
Definition triplet_form.hpp:131
data_t max() const
Definition triplet_form.hpp:174
void hack_size(const index_t in_elem)
Adjusts the size of the container by reserving space and updating the element count.
Definition triplet_form.hpp:214
void csc_condense()
Definition triplet_form.hpp:231
void csc_sort()
Sorts the COO format into the CSC (Compressed Sparse Column) order.
Definition triplet_form.hpp:504
triplet_form strictly_upper() const
Definition triplet_form.hpp:660
Mat< data_t > operator*(const Mat< data_t > &in_mat) const
Definition triplet_form.hpp:267
triplet_form(triplet_form &&) noexcept
Definition triplet_form.hpp:344
triplet_form diagonal() const
Definition triplet_form.hpp:652
triplet_form lower() const
Definition triplet_form.hpp:684
bool is_empty() const
Definition triplet_form.hpp:172
data_t & at(index_t, index_t)
Definition triplet_form.hpp:408
void full_csr_condense()
Definition triplet_form.hpp:236
void csr_condense()
Definition triplet_form.hpp:226
bool is_csc_sorted() const
Definition triplet_form.hpp:170
triplet_form(const SpMat< in_dt > &)
Definition triplet_form.hpp:381
triplet_form(const triplet_form &)
Definition triplet_form.hpp:334
triplet_form & operator-=(const triplet_form &)
Definition triplet_form.hpp:629
index_t * row_mem()
Definition triplet_form.hpp:156
triplet_form & operator=(const triplet_form &)
Definition triplet_form.hpp:355
triplet_form & operator+=(const triplet_form &)
Definition triplet_form.hpp:613
index_t * col_mem()
Definition triplet_form.hpp:158
data_t operator()(const index_t row, const index_t col) const
Definition triplet_form.hpp:195
const index_t n_cols
Definition triplet_form.hpp:129
triplet_form operator-(const triplet_form &in_mat) const
Definition triplet_form.hpp:286
triplet_form & operator/=(T2)
const data_t * val_mem() const
Definition triplet_form.hpp:154
triplet_form operator*(T2) const
Mat< data_t > operator*(const Col< data_t > &in_mat) const
Definition triplet_form.hpp:259
void init(const index_t in_rows, const index_t in_cols, const index_t in_elem)
Definition triplet_form.hpp:189
const index_t n_elem
Definition triplet_form.hpp:130
triplet_form & operator*=(T2)
void init(const index_t in_elem)
Definition triplet_form.hpp:184
const index_t * row_mem() const
Definition triplet_form.hpp:150
triplet_form operator/(T2) const
void print() const
Definition triplet_form.hpp:418
Col< data_t > diag() const
Definition triplet_form.hpp:645
friend class triplet_form
Definition triplet_form.hpp:126
bool is_csr_sorted() const
Definition triplet_form.hpp:168
void assemble(const triplet_form< in_dt, in_it > &in_mat, const std::vector< index_t > &row_shift, const std::vector< index_t > &col_shift, const std::vector< data_t > &scalar)
Definition triplet_form.hpp:251
index_t col(const index_t I) const
Definition triplet_form.hpp:164
data_t val(const index_t I) const
Definition triplet_form.hpp:166
void assemble(const Mat< data_t > &, const Col< uword > &)
Definition triplet_form.hpp:530
const index_t * col_mem() const
Definition triplet_form.hpp:152
index_t row(const index_t I) const
Definition triplet_form.hpp:162
void full_csc_condense()
Definition triplet_form.hpp:242
triplet_form(triplet_form< in_dt, in_it > &, SparseBase=SparseBase::ZERO, bool=false)
Definition triplet_form.hpp:389
index_t index_type
Definition triplet_form.hpp:122
Definition suanPan.h:394
Definition suanPan.h:395
std::string format(const std::string_view format_str, const T &... args)
Definition suanPan.h:318
constexpr T max_element(T start, T end)
Definition utility.h:39
bool approx_equal(T x, T y, int ulp=2)
Definition utility.h:60
void for_each(const IT start, const IT end, F &&FN)
Definition utility.h:28
#define suanpan_info
Definition suanPan.h:369
#define suanpan_for_each
Definition suanPan.h:195
void suanpan_assert(const std::function< void()> &F)
Definition suanPan.h:360
#define suanpan_sort
Definition suanPan.h:194
SparseBase
Definition triplet_form.hpp:27
triplet_form< data_t, index_t > operator+(const triplet_form< data_t, index_t > &mat_a, const triplet_form< data_t, index_t > &mat_b)
Definition triplet_form.hpp:692