batmat 0.0.22
Batched linear algebra routines
Loading...
Searching...
No Matches
norms.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// Vector reductions.
5/// @ingroup topic-utilities
6
7#include <batmat/config.hpp>
8#include <batmat/simd.hpp>
9#include <cmath>
10
11namespace batmat::linalg {
12
13/// @addtogroup topic-utilities
14/// @{
15
16/// Utilities for computing vector norms.
17/// @tparam T Scalar type.
18/// @tparam simd SIMD type. Void for scalar-only.
19template <class T, class simd = void>
20struct norms;
21
22template <class T>
23struct norms<T>;
24
25template <class T, class simd>
26struct norms : norms<T> {
27 /// Accumulator.
28 using result = typename norms<T>::result;
29 /// Lane-wise accumulators.
30 struct result_simd {
31 simd amax;
32 simd asum;
33 simd sumsq;
34
35 /// ℓ₁ norm.
36 [[nodiscard]] simd norm_1() const { return asum; }
37 /// ℓ₂ norm.
38 [[nodiscard]] simd norm_2() const {
39 using std::sqrt;
40 return sqrt(sumsq);
41 }
42 /// max-norm.
43 [[nodiscard]] simd norm_inf() const {
44 using std::isfinite;
45 return datapar::select(isfinite(asum), amax, asum);
46 }
47 };
48
49 using norms<T>::operator();
50
51 /// Update the accumulator with a new value.
52 result_simd operator()(result_simd accum, simd t) const {
53 using std::abs;
54 using std::max;
55 auto at = abs(t);
56 return {.amax = max(at, accum.amax), .asum = at + accum.asum, .sumsq = t * t + accum.sumsq};
57 }
58
59 /// Combine two accumulators.
61 using std::max;
62 return {.amax = max(a.amax, b.amax), .asum = a.asum + b.asum, .sumsq = a.sumsq + b.sumsq};
63 }
64
65 /// Reduce the SIMD accumulator to a scalar result.
67 using batmat::datapar::hmax;
68 return {hmax(accum.amax), reduce(accum.asum), reduce(accum.sumsq)};
69 }
70
71 using norms<T>::zero;
72 static result_simd zero_simd() { return {}; }
73};
74
75template <class T>
76struct norms<T, void> {
77 /// Accumulator.
78 struct result {
79 T amax; ///< Maximum absolute value (ignoring NaNs).
82
83 /// ℓ₁ norm.
84 [[nodiscard]] T norm_1() const { return asum; }
85 /// ℓ₂ norm.
86 [[nodiscard]] T norm_2() const {
87 using std::sqrt;
88 return sqrt(sumsq);
89 }
90 /// max-norm.
91 [[nodiscard]] T norm_inf() const {
92 using std::isfinite;
93 return isfinite(asum) ? amax : asum;
94 }
95 };
96
97 /// Update the accumulator with a new value.
98 result operator()(result accum, T t) const {
99 using std::abs;
100 using std::max;
101 auto at = abs(t);
102 return {.amax = max(at, accum.amax), .asum = at + accum.asum, .sumsq = t * t + accum.sumsq};
103 }
104
105 /// Combine two accumulators.
106 result operator()(result accum, result t) const {
107 using std::max;
108 return {max(accum.amax, t.amax), accum.asum + t.asum, accum.sumsq + t.sumsq};
109 }
110
111 /// Identity element for the reduction.
112 static result zero() { return {}; }
113};
114
115/// @}
116
117} // namespace batmat::linalg
auto select(auto cond, auto t, auto f)
Definition simd.hpp:152
Lane-wise accumulators.
Definition norms.hpp:30
simd norm_inf() const
max-norm.
Definition norms.hpp:43
simd norm_1() const
ℓ₁ norm.
Definition norms.hpp:36
simd norm_2() const
ℓ₂ norm.
Definition norms.hpp:38
T amax
Maximum absolute value (ignoring NaNs).
Definition norms.hpp:79
static result zero()
Identity element for the reduction.
Definition norms.hpp:112
result operator()(result accum, result t) const
Combine two accumulators.
Definition norms.hpp:106
result operator()(result accum, T t) const
Update the accumulator with a new value.
Definition norms.hpp:98
Utilities for computing vector norms.
Definition norms.hpp:26
result operator()(result_simd accum) const
Reduce the SIMD accumulator to a scalar result.
Definition norms.hpp:66
result_simd operator()(result_simd accum, simd t) const
Update the accumulator with a new value.
Definition norms.hpp:52
static result_simd zero_simd()
Definition norms.hpp:72
result_simd operator()(result_simd a, result_simd b) const
Combine two accumulators.
Definition norms.hpp:60
typename norms< T >::result result
Accumulator.
Definition norms.hpp:28