1
#ifndef _RHEOLEF_CSR_CONCAT_H
2
#define _RHEOLEF_CSR_CONCAT_H
4
/// This file is part of Rheolef.
6
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
8
/// Rheolef is free software; you can redistribute it and/or modify
9
/// it under the terms of the GNU General Public License as published by
10
/// the Free Software Foundation; either version 2 of the License, or
11
/// (at your option) any later version.
13
/// Rheolef is distributed in the hope that it will be useful,
14
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
/// GNU General Public License for more details.
18
/// You should have received a copy of the GNU General Public License
19
/// along with Rheolef; if not, write to the Free Software
20
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
/// =========================================================================
23
// build csr from initializer list (c++ 2011)
25
#include "rheolef/csr.h"
29
// =========================================================================
30
// 1rst case : one-line matrix initializer
31
// A = {a, u}; // matrix & vector
32
// A = {trans(u), 3.2}; // trans(vector) & scalar
33
// =========================================================================
34
template <class T, class M>
37
vec_trans (const vec<T,M>& w) : v(w) {}
39
template <class T, class M>
41
trans (const vec<T,M>& w) {
42
return vec_trans<T,M> (w);
45
template <class T, class M>
46
struct csr_concat_value {
48
typedef enum { scalar, vector, vector_transpose, matrix} variant_type;
50
csr_concat_value (const T& x) : s(x), v(), m(), variant(scalar) {}
51
csr_concat_value (const vec<T,M>& x) : s(), v(x), m(), variant(vector) {}
52
csr_concat_value (const vec_trans<T,M>& vt) : s(), v(vt.v), m(), variant(vector_transpose) {}
53
csr_concat_value (const csr<T,M>& x) : s(), v(), m(x), variant(matrix) {}
55
friend std::ostream& operator<< (std::ostream& o, const csr_concat_value<T,M>& x) {
56
if (x.variant == scalar) return o << "s";
57
else if (x.variant == vector) return o << "v";
58
else if (x.variant == vector_transpose) return o << "vt";
69
template <class T, class M>
70
struct csr_concat_line {
72
typedef typename csr<T,M>::size_type size_type;
73
typedef csr_concat_value<T,M> value_type;
75
csr_concat_line () : _l() {}
76
csr_concat_line (const std::initializer_list<value_type>& il) : _l() {
77
#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_ITERATOR
78
typedef typename std::initializer_list<value_type>::const_iterator const_iterator;
79
#else // _RHEOLEF_HAVE_STD_INITIALIZER_ITERATOR
80
typedef const value_type* const_iterator;
81
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_ITERATOR
82
for(const_iterator iter = il.begin(); iter != il.end(); ++iter) {
86
void push_back (const value_type& x) { _l.push_back (x); }
88
friend std::ostream& operator<< (std::ostream& o, const csr_concat_line<T,M>& x) {
90
for(typename std::list<value_type>::const_iterator iter = x._l.begin(); iter != x._l.end(); ++iter) {
91
std::cout << *iter << " ";
93
return std::cout << "}";
96
static void set_sizes (
97
std::pair<size_type,size_type>& row_sizes,
98
std::pair<size_type,size_type>& col_sizes,
99
const std::pair<size_type,size_type>& new_row_sizes,
100
const std::pair<size_type,size_type>& new_col_sizes);
102
static void finalize_sizes (
103
std::pair<size_type,size_type>& sizes,
104
const communicator& comm);
106
static void finalize_sizes (
107
std::vector<std::pair<size_type,size_type> >& sizes,
108
const communicator& comm);
110
void build_csr_pass0 (
111
std::pair<size_type,size_type>& row_sizes,
112
std::vector<std::pair<size_type,size_type> >& col_sizes,
113
communicator& comm) const;
115
void build_csr_pass1 (
116
const std::pair<size_type,size_type>& row_sizes,
117
const std::vector<std::pair<size_type,size_type> >& col_sizes,
118
const communicator& comm,
119
distributor& row_ownership,
120
distributor& col_ownership,
121
std::vector<distributor>& col_start_by_component) const;
123
void build_csr_pass2 (
125
const std::vector<distributor>& col_start_by_component,
126
size_type row_start_comp_i = 0,
127
size_type row_start_comp_dis_i = 0) const;
129
csr<T,M> build_csr () const;
133
std::list<value_type> _l;
135
// ------------------------
137
// ------------------------
138
template <class T, class M>
140
csr_concat_line<T,M>::set_sizes (
141
std::pair<size_type,size_type>& row_sizes,
142
std::pair<size_type,size_type>& col_sizes,
143
const std::pair<size_type,size_type>& new_row_sizes,
144
const std::pair<size_type,size_type>& new_col_sizes)
146
size_type undef = std::numeric_limits<size_type>::max();
147
if (row_sizes.first == undef) {
148
row_sizes = new_row_sizes;
149
} else if (new_row_sizes.first != undef) {
150
check_macro (row_sizes.first == new_row_sizes.first,
151
"matrix initializer list: matrix row argument [0:"
152
<< new_row_sizes.first << "|" << new_row_sizes.second << "["
153
<< " has incomptible size: expect [0:"
154
<< row_sizes.first << "|" << row_sizes.second << "[");
156
if (col_sizes.first == undef) {
157
col_sizes = new_col_sizes;
158
} else if (new_col_sizes.first != undef) {
159
check_macro (col_sizes.first == new_col_sizes.first,
160
"matrix initializer list: matrix col argument [0:"
161
<< new_col_sizes.first << "|" << new_col_sizes.second << "["
162
<< " has incomptible size: expect [0:"
163
<< col_sizes.first << "|" << col_sizes.second << "[");
166
template <class T, class M>
168
csr_concat_line<T,M>::finalize_sizes (
169
std::pair<size_type,size_type>& sizes,
170
const communicator& comm)
172
size_type undef = std::numeric_limits<size_type>::max();
173
if (sizes.first == undef) {
174
sizes.first = (comm.rank() == comm.size() - 1) ? 1 : 0;
178
template <class T, class M>
180
csr_concat_line<T,M>::finalize_sizes (
181
std::vector<std::pair<size_type,size_type> >& sizes,
182
const communicator& comm)
184
for (size_type i_comp = 0; i_comp < sizes.size(); i_comp++) {
185
finalize_sizes (sizes [i_comp], comm);
188
// ------------------------
189
// pass 0 : compute sizes
190
// ------------------------
191
template <class T, class M>
193
csr_concat_line<T,M>::build_csr_pass0 (
194
std::pair<size_type,size_type>& row_sizes,
195
std::vector<std::pair<size_type,size_type> >& col_sizes,
196
communicator& comm) const
198
size_type undef = std::numeric_limits<size_type>::max();
199
if (col_sizes.size() == 0) {
200
col_sizes.resize (_l.size(), std::pair<size_type,size_type>(undef,undef));
202
check_macro (col_sizes.size() == _l.size(),
203
"matrix initializer list: unexpected matrix line size "
204
<< _l.size() << ": size " << col_sizes.size()
207
size_type j_comp = 0;
208
for (typename std::list<value_type>::const_iterator iter = _l.begin(); iter != _l.end(); ++iter, j_comp++) {
209
const value_type& x = *iter;
211
case value_type::matrix: {
212
size_type nrow = x.m.row_ownership().size();
213
size_type dis_nrow = x.m.row_ownership().dis_size();
214
size_type ncol = x.m.col_ownership().size();
215
size_type dis_ncol = x.m.col_ownership().dis_size();
216
set_sizes (row_sizes, col_sizes[j_comp],
217
std::make_pair (nrow, dis_nrow), std::make_pair (ncol, dis_ncol));
218
comm = x.m.row_ownership().comm(); // TODO: check if compatible comm
221
case value_type::vector: {
222
size_type nrow = x.v.ownership().size();
223
size_type dis_nrow = x.v.ownership().dis_size();
224
size_type ncol = (comm.rank() == comm.size() - 1) ? 1 : 0;
225
size_type dis_ncol = 1;
226
set_sizes (row_sizes, col_sizes[j_comp],
227
std::make_pair (nrow, dis_nrow), std::make_pair (ncol, dis_ncol));
228
comm = x.v.comm(); // TODO: check if compatible comm
231
case value_type::vector_transpose: {
232
size_type nrow = (comm.rank() == comm.size() - 1) ? 1 : 0;
233
size_type dis_nrow = 1;
234
size_type ncol = x.v.ownership().size();
235
size_type dis_ncol = x.v.ownership().dis_size();
236
set_sizes (row_sizes, col_sizes[j_comp],
237
std::make_pair (nrow, dis_nrow), std::make_pair (ncol, dis_ncol));
238
comm = x.v.comm(); // TODO: check if compatible comm
241
case value_type::scalar: {
242
size_type nrow = undef;
243
size_type dis_nrow = undef;
244
size_type ncol = undef;
245
size_type dis_ncol = undef;
248
nrow = (comm.rank() == comm.size() - 1) ? 1 : 0;
250
ncol = (comm.rank() == comm.size() - 1) ? 1 : 0;
254
set_sizes (row_sizes, col_sizes[j_comp],
255
std::make_pair (nrow, dis_nrow), std::make_pair (ncol, dis_ncol));
261
// ---------------------------
262
// pass 1 : compute ownership
263
// ---------------------------
264
template <class T, class M>
266
csr_concat_line<T,M>::build_csr_pass1 (
267
const std::pair<size_type,size_type>& row_sizes,
268
const std::vector<std::pair<size_type,size_type> >& col_sizes,
269
const communicator& comm,
270
distributor& row_ownership,
271
distributor& col_ownership,
272
std::vector<distributor>& col_start_by_component) const
274
row_ownership = distributor (row_sizes.second, comm, row_sizes.first);
275
size_type col_comp_start_j = 0;
276
size_type col_comp_start_dis_j = 0;
277
col_start_by_component.resize (col_sizes.size());
278
for (size_type j_comp = 0; j_comp < col_sizes.size(); j_comp++) {
279
col_start_by_component [j_comp] = distributor (col_comp_start_dis_j, comm, col_comp_start_j);
280
col_comp_start_j += col_sizes [j_comp].first;
281
col_comp_start_dis_j += col_sizes [j_comp].second;
283
col_ownership = distributor (col_comp_start_dis_j, comm, col_comp_start_j);
285
// ------------------------
287
// ------------------------
288
template <class T, class M>
290
csr_concat_line<T,M>::build_csr_pass2 (
292
const std::vector<distributor>& col_start_by_component,
293
size_type row_start_comp_i,
294
size_type row_start_comp_dis_i) const
296
communicator comm = a.row_ownership().comm();
297
size_type first_dis_i = a.row_ownership().first_index();
298
size_type first_dis_j = a.col_ownership().first_index();
299
size_type my_proc = comm.rank();
300
size_type last_proc = comm.size() - 1;
301
size_type col_start_comp_dis_j = 0;
302
size_type j_comp = 0;
303
for (typename std::list<value_type>::const_iterator iter = _l.begin(); iter != _l.end(); ++iter, j_comp++) {
304
const value_type& x = *iter;
306
case value_type::matrix: {
307
size_type col_start_comp_j = col_start_by_component[j_comp].size();
308
typename csr<T,M>::const_iterator dia_ia = x.m.begin();
309
typename csr<T,M>::const_iterator ext_ia = x.m.ext_begin();
310
for (size_type i = 0, n = x.m.nrow(); i < n; i++) {
311
size_type dis_i = first_dis_i + row_start_comp_i + i;
312
for (typename csr<T,M>::const_data_iterator p = dia_ia[i]; p < dia_ia[i+1]; p++) {
313
size_type j = (*p).first;
314
size_type dis_j = first_dis_j + col_start_comp_j + j;
315
a.dis_entry (dis_i, dis_j) = (*p).second;
317
if (is_distributed<M>::value && x.m.ext_nnz() != 0) {
318
for (typename csr<T,M>::const_data_iterator p = ext_ia[i]; p < ext_ia[i+1]; p++) {
319
size_type comp_dis_j = x.m.jext2dis_j ((*p).first);
320
size_type iproc = x.m.col_ownership().find_owner (comp_dis_j);
321
size_type first_comp_dis_j_iproc = x.m.col_ownership().first_index (iproc);
322
assert_macro (comp_dis_j >= first_comp_dis_j_iproc, "invalid index");
323
size_type j = comp_dis_j - first_comp_dis_j_iproc;
324
size_type col_start_comp_j_iproc = col_start_by_component[j_comp].size(iproc);
325
size_type first_dis_j_iproc = a.col_ownership().first_index(iproc);
326
size_type dis_j = first_dis_j_iproc + col_start_comp_j_iproc + j;
327
a.dis_entry (dis_i, dis_j) = (*p).second;
331
col_start_comp_dis_j += x.m.col_ownership().dis_size();
334
case value_type::vector: {
335
size_type dis_i = row_start_comp_i + first_dis_i;
336
size_type dis_j = col_start_comp_dis_j;
337
for (typename vec<T,M>::const_iterator iter = x.v.begin(), last = x.v.end(); iter != last; iter++, dis_i++) {
339
a.dis_entry (dis_i, dis_j) = *iter;
342
col_start_comp_dis_j++;
345
case value_type::vector_transpose: {
346
size_type dis_i = row_start_comp_dis_i + 0;
347
size_type dis_j = col_start_comp_dis_j + x.v.ownership().first_index();
348
for (typename vec<T,M>::const_iterator iter = x.v.begin(), last = x.v.end(); iter != last; iter++, dis_j++) {
350
a.dis_entry (dis_i, dis_j) = *iter;
353
col_start_comp_dis_j += x.v.ownership().dis_size();
356
case value_type::scalar: {
357
if (x.s != 0 && comm.rank() == comm.size() - 1) {
358
size_type dis_i = row_start_comp_dis_i + 0;
359
size_type dis_j = col_start_comp_dis_j;
360
a.dis_entry (dis_i, dis_j) = x.s;
362
col_start_comp_dis_j++;
368
// ------------------------------
369
// merge passes 1 & 2
370
// ------------------------------
371
template <class T, class M>
373
csr_concat_line<T,M>::build_csr() const
375
size_type undef = std::numeric_limits<size_type>::max();
376
std::pair<size_type,size_type> row_sizes = std::pair<size_type,size_type>(undef,undef);
377
std::vector<std::pair<size_type,size_type> > col_sizes;
379
build_csr_pass0 (row_sizes, col_sizes, comm);
380
finalize_sizes (row_sizes, comm);
381
finalize_sizes (col_sizes, comm);
382
distributor row_ownership;
383
distributor col_ownership;
384
std::vector<distributor> col_start_by_component;
385
build_csr_pass1 (row_sizes, col_sizes, comm, row_ownership, col_ownership, col_start_by_component);
386
asr<T,M> a (row_ownership, col_ownership);
387
build_csr_pass2 (a, col_start_by_component);
388
a.dis_entry_assembly();
391
// -------------------------------
392
// csr cstor from std::initializer
393
// -------------------------------
394
#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_LIST
395
#define RHEOLEF_csr_cstor(M) \
398
csr<T,M>::csr (const std::initializer_list<csr_concat_value<T,M> >& init_list) \
400
csr_concat_line<T,M> cc (init_list); \
401
csr<T,M>::operator= (cc.build_csr()); \
403
RHEOLEF_csr_cstor(sequential)
404
#ifdef _RHEOLEF_HAVE_MPI
405
RHEOLEF_csr_cstor(distributed)
406
#endif // _RHEOLEF_HAVE_MPI
407
#undef RHEOLEF_csr_cstor
408
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_LIST
409
// =========================================================================
410
// 2nd case : multi-line matrix initializer
412
// {trans(u), 3.2} };
413
// =========================================================================
415
template <class T, class M>
418
typedef typename csr<T,M>::size_type size_type;
419
typedef csr_concat_line<T,M> line_type;
420
typedef csr_concat_value<T,M> value_type;
422
csr_concat () : _l() {}
423
csr_concat (const std::initializer_list<line_type>& il) : _l() {
424
#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_ITERATOR
425
typedef typename std::initializer_list<line_type>::const_iterator const_iterator;
426
#else // _RHEOLEF_HAVE_STD_INITIALIZER_ITERATOR
427
typedef const line_type* const_iterator;
428
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_ITERATOR
429
for(const_iterator iter = il.begin(); iter != il.end(); ++iter) {
433
void push_back (const line_type& line) { _l.push_back(line); }
435
friend std::ostream& operator<< (std::ostream& o, const csr_concat<T,M>& x) {
437
for(typename std::list<line_type>::const_iterator iter = x._l.begin(); iter != x._l.end(); ++iter) {
438
std::cout << *iter << " ";
440
return std::cout << "}";
443
csr<T,M> build_csr () const;
447
std::list<line_type> _l;
449
template <class T, class M>
451
csr_concat<T,M>::build_csr() const
453
// ---------------------------
454
// pass 0 : compute sizes
455
// ---------------------------
456
size_type undef = std::numeric_limits<size_type>::max();
457
std::vector<std::pair<size_type,size_type> > row_sizes (_l.size(), std::pair<size_type,size_type>(undef,undef));
458
std::vector<std::pair<size_type,size_type> > col_sizes;
460
size_type i_comp = 0;
461
for (typename std::list<line_type>::const_iterator iter = _l.begin(); iter != _l.end(); ++iter, i_comp++) {
462
const line_type& line = *iter;
463
line.build_csr_pass0 (row_sizes[i_comp], col_sizes, comm);
465
csr_concat_line<T,M>::finalize_sizes (row_sizes, comm);
466
csr_concat_line<T,M>::finalize_sizes (col_sizes, comm);
467
// ---------------------------
468
// pass 1 : compute ownership
469
// ---------------------------
470
size_type row_comp_start_i = 0;
471
size_type row_comp_start_dis_i = 0;
472
for (size_type i_comp = 0; i_comp < row_sizes.size(); i_comp++) {
473
row_comp_start_i += row_sizes [i_comp].first;
474
row_comp_start_dis_i += row_sizes [i_comp].second;
476
distributor row_ownership = distributor (row_comp_start_dis_i, comm, row_comp_start_i);
478
size_type col_comp_start_j = 0;
479
size_type col_comp_start_dis_j = 0;
480
std::vector<distributor> col_start_by_component (col_sizes.size());
481
for (size_type j_comp = 0; j_comp < col_sizes.size(); j_comp++) {
482
col_start_by_component [j_comp] = distributor (col_comp_start_dis_j, comm, col_comp_start_j);
483
col_comp_start_j += col_sizes [j_comp].first;
484
col_comp_start_dis_j += col_sizes [j_comp].second;
486
distributor col_ownership = distributor (col_comp_start_dis_j, comm, col_comp_start_j);
487
// ------------------------
489
// ------------------------
490
asr<T,M> a (row_ownership, col_ownership);
491
size_type row_start_comp_i = 0;
492
size_type row_start_comp_dis_i = 0;
494
for (typename std::list<line_type>::const_iterator iter = _l.begin(); iter != _l.end(); ++iter, ++i_comp) {
495
const line_type& line = *iter;
496
line.build_csr_pass2 (a, col_start_by_component, row_start_comp_i, row_start_comp_dis_i);
497
row_start_comp_i += row_sizes[i_comp].first;
498
row_start_comp_dis_i += row_sizes[i_comp].second;
500
a.dis_entry_assembly();
503
#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_LIST
504
#define RHEOLEF_csr_cstor(M) \
507
csr<T,M>::csr (const std::initializer_list<csr_concat_line<T,M> >& init_list) \
509
csr_concat<T,M> cc (init_list); \
510
csr<T,M>::operator= (cc.build_csr()); \
512
RHEOLEF_csr_cstor(sequential)
513
#ifdef _RHEOLEF_HAVE_MPI
514
RHEOLEF_csr_cstor(distributed)
515
#endif // _RHEOLEF_HAVE_MPI
516
#undef RHEOLEF_csr_cstor
517
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_LIST
519
} // namespace rheolef
520
#endif // _RHEOLEF_CSR_CONCAT_H