Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
matrix_op.hpp
Go to the documentation of this file.
1// -------------------------------------------------------//
2//
3// SHAMROCK code for hydrodynamics
4// Copyright (c) 2021-2026 Timothée David--Cléris <tim.shamrock@proton.me>
5// SPDX-License-Identifier: CeCILL Free Software License Agreement v2.1
6// Shamrock is licensed under the CeCILL 2.1 License, see LICENSE for more information
7//
8// -------------------------------------------------------//
9
10#pragma once
11
21#include "shambase/assert.hpp"
23#include "shambackends/math.hpp"
24#include "shambackends/sycl.hpp"
25#include <experimental/mdspan>
26#include <array>
27
28namespace shammath {
29
43 template<class T, class Extents, class Layout, class Accessor, class Func>
44 inline void mat_set_vals(const std::mdspan<T, Extents, Layout, Accessor> &input, Func &&func) {
45
47
48 for (int i = 0; i < input.extent(0); i++) {
49 for (int j = 0; j < input.extent(1); j++) {
50 input(i, j) = func(i, j);
51 }
52 }
53 }
54
68 template<class T, class Extents, class Layout, class Accessor, class Func>
69 inline void mat_update_vals(
70 const std::mdspan<T, Extents, Layout, Accessor> &input, Func &&func) {
71
73
74 for (int i = 0; i < input.extent(0); i++) {
75 for (int j = 0; j < input.extent(1); j++) {
76 func(input(i, j), i, j);
77 }
78 }
79 }
80
92 template<class T, class Extents, class Layout, class Accessor>
93 inline void mat_set_identity(const std::mdspan<T, Extents, Layout, Accessor> &input1) {
94
95 SHAM_ASSERT(input1.extent(0) == input1.extent(1));
96
97 mat_set_vals(input1, [](auto i, auto j) -> T {
98 return (i == j) ? 1 : 0;
99 });
100 }
101
111 template<class T, class Extents, class Layout, class Accessor>
112 inline void mat_mul_scalar(
113 const std::mdspan<T, Extents, Layout, Accessor> &input, const T &scalar) {
114 mat_update_vals(input, [&](T &v, auto i, auto j) {
115 v *= scalar;
116 });
117 }
118
128 template<class T, class Extents, class Layout, class Accessor>
129 inline void mat_copy(
130 const std::mdspan<T, Extents, Layout, Accessor> &input,
131 const std::mdspan<T, Extents, Layout, Accessor> &output) {
132
133 SHAM_ASSERT(input.extent(0) == output.extent(0));
134 SHAM_ASSERT(input.extent(1) == output.extent(1));
135
136 for (int i = 0; i < input.extent(0); i++) {
137 for (int j = 0; j < input.extent(1); j++) {
138 output(i, j) = input(i, j);
139 }
140 }
141 }
142
154 template<
155 class T,
156 class Extents1,
157 class Extents2,
158 class Extents3,
159 class Layout1,
160 class Layout2,
161 class Layout3,
162 class Accessor1,
163 class Accessor2,
164 class Accessor3>
165 inline void mat_plus(
166 const std::mdspan<T, Extents1, Layout1, Accessor1> &input1,
167 const std::mdspan<T, Extents2, Layout2, Accessor2> &input2,
168 const std::mdspan<T, Extents3, Layout3, Accessor3> &output) {
169
170 SHAM_ASSERT(input1.extent(0) == output.extent(0));
171 SHAM_ASSERT(input1.extent(1) == output.extent(1));
172 SHAM_ASSERT(input1.extent(0) == input2.extent(0));
173 SHAM_ASSERT(input1.extent(1) == input2.extent(1));
174
175 for (int i = 0; i < input1.extent(0); i++) {
176 for (int j = 0; j < input1.extent(1); j++) {
177 output(i, j) = input1(i, j) + input2(i, j);
178 }
179 }
180 }
181
192 template<
193 class T,
194 class Extents1,
195 class Extents2,
196 class Layout1,
197 class Layout2,
198 class Accessor1,
199 class Accessor2>
200 inline void mat_plus_equal(
201 const std::mdspan<T, Extents1, Layout1, Accessor1> &inout,
202 const std::mdspan<T, Extents2, Layout2, Accessor2> &matb) {
203
204 SHAM_ASSERT(inout.extent(0) == inout.extent(0));
205 SHAM_ASSERT(inout.extent(1) == inout.extent(1));
206
207 for (int i = 0; i < inout.extent(0); i++) {
208 for (int j = 0; j < inout.extent(1); j++) {
209 inout(i, j) += matb(i, j);
210 }
211 }
212 }
213
225 template<
226 class T,
227 class Extents1,
228 class Extents2,
229 class Extents3,
230 class Layout1,
231 class Layout2,
232 class Layout3,
233 class Accessor1,
234 class Accessor2,
235 class Accessor3>
236 inline void mat_sub(
237 const std::mdspan<T, Extents1, Layout1, Accessor1> &input1,
238 const std::mdspan<T, Extents2, Layout2, Accessor2> &input2,
239 const std::mdspan<T, Extents3, Layout3, Accessor3> &output) {
240
241 SHAM_ASSERT(input1.extent(0) == output.extent(0));
242 SHAM_ASSERT(input1.extent(1) == output.extent(1));
243 SHAM_ASSERT(input1.extent(0) == input2.extent(0));
244 SHAM_ASSERT(input1.extent(1) == input2.extent(1));
245
246 for (int i = 0; i < input1.extent(0); i++) {
247 for (int j = 0; j < input1.extent(1); j++) {
248 output(i, j) = input1(i, j) - input2(i, j);
249 }
250 }
251 }
252
264 template<
265 class T,
266 class Extents1,
267 class Extents2,
268 class Layout1,
269 class Layout2,
270 class Accessor1,
271 class Accessor2>
272 inline void mat_sub_equal(
273 const std::mdspan<T, Extents1, Layout1, Accessor1> &inout,
274 const std::mdspan<T, Extents2, Layout2, Accessor2> &matb) {
275
276 SHAM_ASSERT(inout.extent(0) == inout.extent(0));
277 SHAM_ASSERT(inout.extent(1) == inout.extent(1));
278
279 for (int i = 0; i < inout.extent(0); i++) {
280 for (int j = 0; j < inout.extent(1); j++) {
281 inout(i, j) -= matb(i, j);
282 }
283 }
284 }
285
304 template<
305 class Ta,
306 class Tb,
307 class Extents1,
308 class Extents2,
309 class Extents3,
310 class Layout1,
311 class Layout2,
312 class Layout3,
313 class Accessor1,
314 class Accessor2,
315 class Accessor3>
316 inline void mat_prod(
317 const std::mdspan<Ta, Extents1, Layout1, Accessor1> &input1,
318 const std::mdspan<Ta, Extents2, Layout2, Accessor2> &input2,
319 const std::mdspan<Tb, Extents3, Layout3, Accessor3> &output) {
320
321 SHAM_ASSERT(input1.extent(0) == output.extent(0));
322 SHAM_ASSERT(input1.extent(1) == input2.extent(0));
323 SHAM_ASSERT(input2.extent(1) == output.extent(1));
324
325 // output_ij = mat1_ik mat2_jk
326 for (int i = 0; i < input1.extent(0); i++) {
327 for (int j = 0; j < input2.extent(1); j++) {
328 Tb sum = 0;
329 for (int k = 0; k < input1.extent(1); k++) {
330 sum += input1(i, k) * input2(k, j);
331 }
332 output(i, j) = sum;
333 }
334 }
335 }
336
350 template<class T, class SizeType, class Layout, class Accessor>
351 inline void mat_inv_33(
352 const std::mdspan<T, std::extents<SizeType, 3, 3>, Layout, Accessor> &input,
353 const std::mdspan<T, std::extents<SizeType, 3, 3>, Layout, Accessor> &output) {
354
355 T &a00 = input(0, 0);
356 T &a10 = input(1, 0);
357 T &a20 = input(2, 0);
358
359 T &a01 = input(0, 1);
360 T &a11 = input(1, 1);
361 T &a21 = input(2, 1);
362
363 T &a02 = input(0, 2);
364 T &a12 = input(1, 2);
365 T &a22 = input(2, 2);
366
367 T det
368 = (-a02 * a11 * a20 + a01 * a12 * a20 + a02 * a10 * a21 - a00 * a12 * a21
369 - a01 * a10 * a22 + a00 * a11 * a22);
370
371 output(0, 0) = (-a12 * a21 + a11 * a22) / det;
372 output(1, 0) = (a12 * a20 - a10 * a22) / det;
373 output(2, 0) = (-a11 * a20 + a10 * a21) / det;
374
375 output(0, 1) = (a02 * a21 - a01 * a22) / det;
376 output(1, 1) = (-a02 * a20 + a00 * a22) / det;
377 output(2, 1) = (a01 * a20 - a00 * a21) / det;
378
379 output(0, 2) = (-a02 * a11 + a01 * a12) / det;
380 output(1, 2) = (a02 * a10 - a00 * a12) / det;
381 output(2, 2) = (-a01 * a10 + a00 * a11) / det;
382 }
383
393 template<class T, class U, class Extents, class Layout, class Accessor>
394 inline void mat_L1_norm(const std::mdspan<T, Extents, Layout, Accessor> &input, U &res) {
395 res = 0;
396 for (auto i = 0; i < input.extent(0); i++) {
397 T sum = 0;
398 for (auto j = 0; j < input.extent(1); j++) {
399 sum += abs(input(i, j));
400 }
401 res = sham::max(res, sum);
402 }
403 }
404
410 template<class T, class Extents, class Layout, class Accessor>
411 inline void mat_set_nul(const std::mdspan<T, Extents, Layout, Accessor> &input) {
412 mat_set_vals(input, [](auto i, auto j) -> T {
413 return 0;
414 });
415 }
416
422 template<class T, class Extents, class Layout, class Accessor>
423 inline void vec_set_nul(const std::mdspan<T, Extents, Layout, Accessor> &input) {
424 for (auto i = 0; i < input.extent(0); i++) {
425 input(i) = 0;
426 }
427 }
428
435 template<class T, class Extents, class Layout, class Accessor>
436 inline void vec_copy(
437 const std::mdspan<T, Extents, Layout, Accessor> &input,
438 const std::mdspan<T, Extents, Layout, Accessor> &output) {
439 SHAM_ASSERT(input.extent(0) == output.extent(0));
440
441 for (int i = 0; i < input.extent(0); i++) {
442 output(i) = input(i);
443 }
444 }
445
454 template<
455 class T,
456 class U,
457 class Extents1,
458 class Extents2,
459 class Layout1,
460 class Layout2,
461 class Accessor1,
462 class Accessor2>
463 inline void vec_axpy_beta(
464 const U alpha,
465 const std::mdspan<T, Extents1, Layout1, Accessor1> &input,
466 const U beta,
467 const std::mdspan<T, Extents2, Layout2, Accessor2> &output) {
468
469 SHAM_ASSERT(input.extent(0) == output.extent(0));
470
471 for (int i = 0; i < input.extent(0); i++) {
472 output(i) = alpha * input(i) + beta * output(i);
473 }
474 }
475
483 template<
484 class T,
485 class U,
486 class Extents1,
487 class Extents2,
488 class Layout1,
489 class Layout2,
490 class Accessor1,
491 class Accessor2>
492 inline void vec_axpy(
493 const U alpha,
494 const std::mdspan<T, Extents1, Layout1, Accessor1> &input,
495 const std::mdspan<T, Extents2, Layout2, Accessor2> &output) {
496
497 vec_axpy_beta(alpha, input, U{1}, output);
498 }
499
508 template<
509 class T,
510 class U,
511 class Extents1,
512 class Extents2,
513 class Layout1,
514 class Layout2,
515 class Accessor1,
516 class Accessor2>
517 inline void mat_axpy_beta(
518 const U alpha,
519 const std::mdspan<T, Extents1, Layout1, Accessor1> &input,
520 const U beta,
521 const std::mdspan<T, Extents2, Layout2, Accessor2> &output) {
522
523 SHAM_ASSERT(input.extent(0) == output.extent(0));
524 SHAM_ASSERT(input.extent(1) == output.extent(1));
525
526 for (int i = 0; i < input.extent(0); i++) {
527 for (int j = 0; j < input.extent(1); j++) {
528 output(i, j) = alpha * input(i, j) + beta * output(i, j);
529 }
530 }
531 }
532
540 template<
541 class T,
542 class U,
543 class Extents1,
544 class Extents2,
545 class Layout1,
546 class Layout2,
547 class Accessor1,
548 class Accessor2>
549 inline void mat_axpy(
550 const U alpha,
551 const std::mdspan<T, Extents1, Layout1, Accessor1> &input,
552 const std::mdspan<T, Extents2, Layout2, Accessor2> &output) {
553
554 mat_axpy_beta(alpha, input, U{1}, output);
555 }
556
566 template<
567 class T,
568 class U,
569 class Extents1,
570 class Extents2,
571 class Extents3,
572 class Layout1,
573 class Layout2,
574 class Layout3,
575 class Accessor1,
576 class Accessor2,
577 class Accessor3>
578 inline void mat_gemm(
579 const U alpha,
580 const std::mdspan<T, Extents1, Layout1, Accessor1> &input1,
581 const std::mdspan<T, Extents2, Layout2, Accessor2> &input2,
582 const U beta,
583 const std::mdspan<T, Extents3, Layout3, Accessor3> &output) {
584
585 SHAM_ASSERT(input1.extent(0) == output.extent(0));
586 SHAM_ASSERT(input1.extent(1) == input2.extent(0));
587 SHAM_ASSERT(input2.extent(1) == output.extent(1));
588
589 for (int i = 0; i < input1.extent(0); i++) {
590 for (int j = 0; j < input2.extent(1); j++) {
591 T sum = 0;
592 for (int k = 0; k < input1.extent(1); k++) {
593 sum += input1(i, k) * input2(k, j);
594 }
595 output(i, j) = alpha * sum + beta * output(i, j);
596 }
597 }
598 }
599
609 template<class T, class U, class Extents1, class Layout1, class Accessor1>
611 const std::mdspan<T, Extents1, Layout1, Accessor1> &inout, const U beta) {
612 for (int i = 0; i < inout.extent(0); i++) {
613 inout(i, i) = inout(i, i) + beta;
614 }
615 }
616
625 template<
626 class T,
627 class U,
628 class Extents1,
629 class Extents2,
630 class Extents3,
631 class Layout1,
632 class Layout2,
633 class Layout3,
634 class Accessor1,
635 class Accessor2,
636 class Accessor3>
637 inline void mat_gemv(
638 const U alpha,
639 const std::mdspan<T, Extents1, Layout1, Accessor1> &M,
640 const std::mdspan<T, Extents2, Layout2, Accessor2> &x,
641 const U beta,
642 const std::mdspan<T, Extents3, Layout3, Accessor3> &y) {
643
644 SHAM_ASSERT(M.extent(1) == x.extent(0));
645 SHAM_ASSERT(M.extent(0) == y.extent(0));
646
647 for (int i = 0; i < M.extent(0); i++) {
648 T sum = 0;
649 for (int j = 0; j < M.extent(1); j++) {
650 sum += M(i, j) * x(j);
651 }
652 y(i) = alpha * sum + beta * y(i);
653 }
654 }
655
656} // namespace shammath
Shamrock assertion utility.
#define SHAM_ASSERT(x)
Shorthand for SHAM_ASSERT_NAMED without a message.
Definition assert.hpp:67
void throw_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Throw an exception and append the source location to it.
namespace for math utility
Definition AABB.hpp:26
void vec_axpy(const U alpha, const std::mdspan< T, Extents1, Layout1, Accessor1 > &input, const std::mdspan< T, Extents2, Layout2, Accessor2 > &output)
This function compute y = alpha*x + y with x,y both vectors.
void mat_plus(const std::mdspan< T, Extents1, Layout1, Accessor1 > &input1, const std::mdspan< T, Extents2, Layout2, Accessor2 > &input2, const std::mdspan< T, Extents3, Layout3, Accessor3 > &output)
Add two matrices element-wise.
void mat_mul_scalar(const std::mdspan< T, Extents, Layout, Accessor > &input, const T &scalar)
Multiply a matrix by a scalar value.
void vec_axpy_beta(const U alpha, const std::mdspan< T, Extents1, Layout1, Accessor1 > &input, const U beta, const std::mdspan< T, Extents2, Layout2, Accessor2 > &output)
This function compute y = alpha*x + beta*y with x,y both vectors.
void mat_gemm(const U alpha, const std::mdspan< T, Extents1, Layout1, Accessor1 > &input1, const std::mdspan< T, Extents2, Layout2, Accessor2 > &input2, const U beta, const std::mdspan< T, Extents3, Layout3, Accessor3 > &output)
This function compute C = alpha*A*B + beta*C with A,B,C are matrices.
void vec_copy(const std::mdspan< T, Extents, Layout, Accessor > &input, const std::mdspan< T, Extents, Layout, Accessor > &output)
Copy the content of one vector in another.
void mat_L1_norm(const std::mdspan< T, Extents, Layout, Accessor > &input, U &res)
compute the L1 norm of a given matrix
void mat_set_nul(const std::mdspan< T, Extents, Layout, Accessor > &input)
Set the content of a matrix to zero.
void mat_set_vals(const std::mdspan< T, Extents, Layout, Accessor > &input, Func &&func)
Set the elements of a matrix according to a user-provided function.
Definition matrix_op.hpp:44
void mat_inv_33(const std::mdspan< T, std::extents< SizeType, 3, 3 >, Layout, Accessor > &input, const std::mdspan< T, std::extents< SizeType, 3, 3 >, Layout, Accessor > &output)
Compute the inverse of a 3x3 matrix.
void mat_axpy_beta(const U alpha, const std::mdspan< T, Extents1, Layout1, Accessor1 > &input, const U beta, const std::mdspan< T, Extents2, Layout2, Accessor2 > &output)
This function compute M = alpha*N + beta*M with M,N both matrices.
void mat_plus_equal_scalar_id(const std::mdspan< T, Extents1, Layout1, Accessor1 > &inout, const U beta)
This function compute addition of a matrix with mutiple of identity matrix A +=beta * I,...
void mat_plus_equal(const std::mdspan< T, Extents1, Layout1, Accessor1 > &inout, const std::mdspan< T, Extents2, Layout2, Accessor2 > &matb)
Add a matrix to another matrix element-wise and store the result in the first matrix.
void mat_sub_equal(const std::mdspan< T, Extents1, Layout1, Accessor1 > &inout, const std::mdspan< T, Extents2, Layout2, Accessor2 > &matb)
Subtract a matrix from another matrix element-wise and store the result in the first matrix.
void mat_axpy(const U alpha, const std::mdspan< T, Extents1, Layout1, Accessor1 > &input, const std::mdspan< T, Extents2, Layout2, Accessor2 > &output)
This function compute M = alpha*N + beta*M with M,N both matrices.
void mat_copy(const std::mdspan< T, Extents, Layout, Accessor > &input, const std::mdspan< T, Extents, Layout, Accessor > &output)
Copy a matrix to another matrix.
void vec_set_nul(const std::mdspan< T, Extents, Layout, Accessor > &input)
Set the content of a vector to zero.
void mat_set_identity(const std::mdspan< T, Extents, Layout, Accessor > &input1)
Set the content of a matrix to the identity matrix.
Definition matrix_op.hpp:93
void mat_prod(const std::mdspan< Ta, Extents1, Layout1, Accessor1 > &input1, const std::mdspan< Ta, Extents2, Layout2, Accessor2 > &input2, const std::mdspan< Tb, Extents3, Layout3, Accessor3 > &output)
Compute the product of two matrices.
void mat_sub(const std::mdspan< T, Extents1, Layout1, Accessor1 > &input1, const std::mdspan< T, Extents2, Layout2, Accessor2 > &input2, const std::mdspan< T, Extents3, Layout3, Accessor3 > &output)
Subtract two matrices element-wise.
void mat_update_vals(const std::mdspan< T, Extents, Layout, Accessor > &input, Func &&func)
Update the elements of a matrix according to a user-provided function.
Definition matrix_op.hpp:69
void mat_gemv(const U alpha, const std::mdspan< T, Extents1, Layout1, Accessor1 > &M, const std::mdspan< T, Extents2, Layout2, Accessor2 > &x, const U beta, const std::mdspan< T, Extents3, Layout3, Accessor3 > &y)
This function performs matrix-vector multiplication as y = a*Mx + b*y.
Traits for C++ types.