Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
CSRMatrix.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* CSRMatrix.h (C) 2000-2026 */
9/* */
10/* Sparse matrix stored in CSR (Compressed Sparse Row) format. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_ALINA_CSRMATRIX_H
13#define ARCCORE_ALINA_CSRMATRIX_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16/*
17 * This file is based on the work on AMGCL library (version march 2026)
18 * which can be found at https://github.com/ddemidov/amgcl.
19 *
20 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
21 * SPDX-License-Identifier: MIT
22 */
23/*---------------------------------------------------------------------------*/
24/*---------------------------------------------------------------------------*/
25
26#include "arccore/alina/AlinaGlobal.h"
27#include "arccore/alina/AlinaUtils.h"
28
29// A supprimer
30#include "arccore/alina/BackendInterface.h"
31
32#include <cstddef>
33#include <numeric>
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace Arcane::Alina
39{
40
42template <typename DataType>
43class CSRArray
44{
45 public:
46
47 using val_type = DataType;
48
49 CSRArray() = default;
50 CSRArray(const CSRArray&) = delete;
51 CSRArray& operator=(const CSRArray&) = delete;
52 ~CSRArray()
53 {
54 // Do not free memory here because we are not the owner
55 // if own_data is false. The CSRMatrix will handle that.
56 }
57
58 public:
59
60 val_type& operator[](Int64 i) { return ptr[i]; }
61 const val_type& operator[](Int64 i) const { return ptr[i]; }
62 operator val_type*() { return ptr; }
63 operator const val_type*() const { return ptr; }
64 val_type* operator+(Int64 i) { return ptr + i; }
65 const val_type* operator+(Int64 i) const { return ptr + i; }
66 val_type* data() { return ptr; }
67 const val_type* data() const { return ptr; }
68
69 public:
70
72 void resize(size_t new_size)
73 {
74 ptr = new val_type[new_size];
75 }
76 void reset()
77 {
78 delete[] ptr;
79 ptr = nullptr;
80 }
81 void setPointerZeroCopy(val_type* new_ptr)
82 {
83 ptr = new_ptr;
84 }
85
86 private:
87
88 val_type* ptr = nullptr;
89};
90
91/*---------------------------------------------------------------------------*/
92/*---------------------------------------------------------------------------*/
96template <typename val_t, typename col_t, typename ptr_t>
97struct CSRMatrix
98{
99 typedef val_t value_type;
100 typedef val_t val_type;
101 typedef col_t col_type;
102 typedef ptr_t ptr_type;
103
104 private:
105 size_t m_nb_row = 0;
106 public:
107 size_t ncols = 0;
108private:
109 size_t m_nb_non_zero = 0;
110public:
114 bool own_data = true;
115
116 [[nodiscard]] size_t nbRow() const noexcept { return m_nb_row; }
117 void setNbRow(size_t v) { m_nb_row = v; }
118
119 [[nodiscard]] size_t nbNonZero() const noexcept { return m_nb_non_zero; }
120 void setNbNonZero(size_t v) { m_nb_non_zero = v; }
121
122 public:
123
124 CSRMatrix() = default;
125
126 template <class PtrRange, class ColRange, class ValRange>
127 CSRMatrix(size_t nrows, size_t ncols, const PtrRange& ptr_range, const ColRange& col_range, const ValRange& val_range)
128 : m_nb_row(nrows)
129 , ncols(ncols)
130 {
131 ARCCORE_ALINA_TIC("CSR copy");
132 precondition(static_cast<ptrdiff_t>(nrows + 1) == std::distance(std::begin(ptr_range), std::end(ptr_range)),
133 "ptr_range has wrong size in crs constructor");
134
135 m_nb_non_zero = ptr_range[nrows];
136
137 precondition(static_cast<ptrdiff_t>(m_nb_non_zero) == std::distance(std::begin(col_range), std::end(col_range)),
138 "col_range has wrong size in crs constructor");
139
140 precondition(static_cast<ptrdiff_t>(m_nb_non_zero) == std::distance(std::begin(val_range), std::end(val_range)),
141 "val_range has wrong size in crs constructor");
142
143 ptr.resize(nrows + 1);
144 col.resize(m_nb_non_zero);
145 val.resize(m_nb_non_zero);
146
147 ptr[0] = ptr_range[0];
148 arccoreParallelFor(0, nrows, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
149 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
150
151 ptr[i + 1] = ptr_range[i + 1];
152 for (auto j = ptr_range[i]; j < ptr_range[i + 1]; ++j) {
153 col[j] = col_range[j];
154 val[j] = val_range[j];
155 }
156 }
157 });
158 ARCCORE_ALINA_TOC("CSR copy");
159 }
160
161 // TODO: A supprimer. Mettre cela dans une function externe pour ne pas dépendre de backend
162 template <class Matrix>
163 CSRMatrix(const Matrix& A)
164 : m_nb_row(backend::nbRow(A))
165 , ncols(backend::nbColumn(A))
166 {
167 ARCCORE_ALINA_TIC("CSR copy");
168 ptr.resize(m_nb_row + 1);
169 ptr[0] = 0;
170
171 arccoreParallelFor(0, m_nb_row, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
172 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
173 int row_width = 0;
174 for (auto a = backend::row_begin(A, i); a; ++a)
175 ++row_width;
176 ptr[i + 1] = row_width;
177 }
178 });
179
180 m_nb_non_zero = scan_row_sizes();
181 col.resize(m_nb_non_zero);
182 val.resize(m_nb_non_zero);
183
184 arccoreParallelFor(0, m_nb_row, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
185 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
186 ptr_type row_head = ptr[i];
187 for (auto a = backend::row_begin(A, i); a; ++a) {
188 col[row_head] = a.col();
189 val[row_head] = a.value();
190
191 ++row_head;
192 }
193 }
194 });
195 ARCCORE_ALINA_TOC("CSR copy");
196 }
197
198 CSRMatrix(const CSRMatrix& other)
199 : m_nb_row(other.m_nb_row)
200 , ncols(other.ncols)
201 , m_nb_non_zero(other.m_nb_non_zero)
202 {
203 if (other.ptr && other.col && other.val) {
204 ptr.resize(m_nb_row + 1);
205 col.resize(m_nb_non_zero);
206 val.resize(m_nb_non_zero);
207
208 ptr[0] = other.ptr[0];
209 arccoreParallelFor(0, m_nb_row, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
210 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
211 ptr[i + 1] = other.ptr[i + 1];
212 for (ptr_type j = other.ptr[i]; j < other.ptr[i + 1]; ++j) {
213 col[j] = other.col[j];
214 val[j] = other.val[j];
215 }
216 }
217 });
218 }
219 }
220
221 CSRMatrix(CSRMatrix&& other) noexcept
222 : m_nb_row(other.m_nb_row)
223 , ncols(other.ncols)
224 , m_nb_non_zero(other.m_nb_non_zero)
225 , ptr(other.ptr)
226 , col(other.col)
227 , val(other.val)
228 , own_data(other.own_data)
229 {
230 other.m_nbRow = 0;
231 other.ncols = 0;
232 other.m_nb_non_zero = 0;
233 other.ptr = 0;
234 other.col = 0;
235 other.val = 0;
236 }
237
238 CSRMatrix& operator=(const CSRMatrix& other)
239 {
240 free_data();
241
242 m_nb_row = other.m_nb_row;
243 ncols = other.ncols;
244 m_nb_non_zero = other.m_nb_non_zero;
245
246 if (other.ptr && other.col && other.val) {
247 ptr = new ptr_type[m_nb_row + 1];
248 col = new col_type[m_nb_non_zero];
249 val = new val_type[m_nb_non_zero];
250
251 ptr[0] = other.ptr[0];
252 arccoreParallelFor(0, m_nb_row, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
253 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
254 ptr[i + 1] = other.ptr[i + 1];
255 for (ptr_type j = other.ptr[i]; j < other.ptr[i + 1]; ++j) {
256 col[j] = other.col[j];
257 val[j] = other.val[j];
258 }
259 }
260 });
261 }
262
263 return *this;
264 }
265
266 CSRMatrix& operator=(CSRMatrix&& other) noexcept
267 {
268 std::swap(m_nb_row, other.m_nb_row);
269 std::swap(ncols, other.ncols);
270 std::swap(m_nb_non_zero, other.m_nb_non_zero);
271 std::swap(ptr, other.ptr);
272 std::swap(col, other.col);
273 std::swap(val, other.val);
274 std::swap(own_data, other.own_data);
275
276 return *this;
277 }
278
279 void free_data()
280 {
281 if (own_data) {
282 ptr.reset();
283 col.reset();
284 val.reset();
285 }
286 }
287
288 void set_size(size_t n, size_t m, bool clean_ptr = false)
289 {
290 precondition(!ptr, "matrix data has already been allocated!");
291
292 m_nb_row = n;
293 ncols = m;
294
295 ptr.resize(m_nb_row + 1);
296
297 if (clean_ptr) {
298 ptr[0] = 0;
299 arccoreParallelFor(0, m_nb_row, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
300 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
301 ptr[i + 1] = 0;
302 }
303 });
304 }
305 }
306
307 ptr_type scan_row_sizes()
308 {
309 std::partial_sum(ptr.data(), ptr.data() + m_nb_row + 1, ptr.data());
310 return ptr[m_nb_row];
311 }
312
313 void set_nonzeros()
314 {
315 set_nonzeros(ptr[m_nb_row]);
316
317 arccoreParallelFor(0, m_nb_row, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
318 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
319 ptrdiff_t row_beg = ptr[i];
320 ptrdiff_t row_end = ptr[i + 1];
321 for (ptrdiff_t j = row_beg; j < row_end; ++j) {
322 col[j] = 0;
323 val[j] = math::zero<val_type>();
324 }
325 }
326 });
327 }
328
329 void set_nonzeros(size_t n, bool need_values = true)
330 {
331 precondition(!col && !val, "matrix data has already been allocated!");
332
333 m_nb_non_zero = n;
334
335 col.resize(m_nb_non_zero);
336
337 if (need_values)
338 val.resize(m_nb_non_zero);
339 }
340
341 ~CSRMatrix()
342 {
343 free_data();
344 }
345
346 class row_iterator
347 {
348 public:
349
350 row_iterator(const col_type* col, const col_type* end, const val_type* val)
351 : m_col(col)
352 , m_end(end)
353 , m_val(val)
354 {}
355
356 operator bool() const
357 {
358 return m_col < m_end;
359 }
360
361 row_iterator& operator++()
362 {
363 ++m_col;
364 ++m_val;
365 return *this;
366 }
367
368 col_type col() const
369 {
370 return *m_col;
371 }
372
373 val_type value() const
374 {
375 return *m_val;
376 }
377
378 private:
379
380 const col_type* m_col = nullptr;
381 const col_type* m_end = nullptr;
382 const val_type* m_val = nullptr;
383 };
384
385 row_iterator row_begin(size_t row) const
386 {
387 ptr_type p = ptr[row];
388 ptr_type e = ptr[row + 1];
389 return row_iterator(col + p, col + e, val + p);
390 }
391
392 size_t bytes() const
393 {
394 if (own_data) {
395 return sizeof(ptr_type) * (m_nb_row + 1) + sizeof(col_type) * m_nb_non_zero + sizeof(val_type) * m_nb_non_zero;
396 }
397 else {
398 return 0;
399 }
400 }
401};
402
403/*---------------------------------------------------------------------------*/
404/*---------------------------------------------------------------------------*/
405
406} // namespace Arcane::Alina
407
408/*---------------------------------------------------------------------------*/
409/*---------------------------------------------------------------------------*/
410
411#endif
Array for internal CSRMatrix fields.
Definition CSRMatrix.h:44
void resize(size_t new_size)
Set the new size. WARNING: this method do not handle the delete of the current value.
Definition CSRMatrix.h:72
Informations d'exécution d'une boucle.
Matrix class, to be used by user.
std::int64_t Int64
Type entier signé sur 64 bits.
void arccoreParallelFor(const ComplexForLoopRanges< RankValue > &loop_ranges, const ForLoopRunInfo &run_info, const LambdaType &lambda_function, const ReducerArgs &... reducer_args)
Applique en concurrence la fonction lambda lambda_function sur l'intervalle d'itération donné par loo...
Definition ParallelFor.h:85
std::int32_t Int32
Type entier signé sur 32 bits.