MADNESS 0.10.1
kahan_accumulator.h
Go to the documentation of this file.
1//
2// Created by Eduard Valeyev on 10/02/21.
3//
4
5#ifndef MADNESS_MISC_KAHAN_ACCUMULATOR_H_
6#define MADNESS_MISC_KAHAN_ACCUMULATOR_H_
7
8#include <iosfwd>
9#include <type_traits>
10
11namespace madness {
12
13template <typename T, typename Enabler = void>
15
16/// implements Kahan summation for real numbers
17template <typename Real>
18struct KahanAccumulator<Real,
19 std::enable_if_t<std::is_floating_point_v<Real>>> {
20 KahanAccumulator() = default;
23
24 template <typename Real_,
25 typename = std::enable_if_t<std::is_floating_point_v<Real_>>>
26 KahanAccumulator(Real_ v) : value_(v) {}
27
28 KahanAccumulator(Real v, Real c) : value_(v), correction_(c) {}
29
30 template <typename Real_>
32 : value_(v.value_), correction_(v.correction_) {}
33
34 explicit operator Real() const { return value_ + correction_; }
35
36 template <typename Real_,
37 typename = std::enable_if_t<std::is_floating_point_v<Real_>>>
39 volatile auto y = v - correction_;
40 volatile auto t = value_ + y;
41 correction_ = (t - value_) - y;
42 value_ = t;
43 return *this;
44 }
45
46 template <typename Real_,
47 typename = std::enable_if_t<std::is_floating_point_v<Real_>>>
49 volatile auto minus_y = v + correction_;
50 volatile auto t = value_ - minus_y;
51 correction_ = (t - value_) + minus_y;
52 value_ = t;
53 return *this;
54 }
55
56 template <typename Real_>
58 *this += v.correction_;
59 *this += v.value_;
60 return *this;
61 }
62
63 template <typename Real_>
65 *this -= v.correction_;
66 *this -= v.value_;
67 return *this;
68 }
69
71 return KahanAccumulator(-value_, -correction_);
72 }
73
74 auto value() const { return value_; }
75 auto correction() const { return correction_; }
76
77 template <typename Archive>
78 void serialize(Archive& ar) {
79 ar& value_& correction_;
80 }
81
82 private:
83 Real value_ = Real{0};
84 Real correction_ = Real{0};
85};
86
87template <typename Real1, typename Real2>
89 KahanAccumulator<decltype(std::declval<Real1>() + std::declval<Real2>())>
90 result(v1);
91 result += v2;
92 return result;
93}
94
95template <typename Real1, typename Real2>
97 KahanAccumulator<decltype(std::declval<Real1>() + std::declval<Real2>())>
98 result(v1);
99 result += v2;
100 return result;
101}
102
103template <typename Real1, typename Real2>
105 KahanAccumulator<decltype(std::declval<Real1>() + std::declval<Real2>())>
106 result(v1);
107 result += v2;
108 return result;
109}
110
111template <typename Real1, typename Real2>
113 KahanAccumulator<decltype(std::declval<Real1>() - std::declval<Real2>())>
114 result(v1);
115 result -= v2;
116 return result;
117}
118
119template <typename Real1, typename Real2>
121 KahanAccumulator<decltype(std::declval<Real2>() - std::declval<Real1>())>
122 result(v2);
123 result -= v1;
124 return result;
125}
126
127template <typename Real1, typename Real2>
129 KahanAccumulator<decltype(std::declval<Real1>() - std::declval<Real2>())>
130 result(v1);
131 result -= v2;
132 return result;
133}
134
135template <typename Char, typename Real>
136std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& os,
137 const KahanAccumulator<Real>& v) {
138 os << "{" << v.value() << "," << v.correction() << "}";
139 return os;
140}
141
142/// implements Kahan summation for complex numbers
143template <typename Complex>
144struct KahanAccumulator<Complex,
145 std::enable_if_t<!std::is_floating_point_v<Complex>>> {
146 using Real = typename Complex::value_type;
148
149 KahanAccumulator() = default;
152
153 template <typename Complex_,
154 typename = std::enable_if_t<!std::is_floating_point_v<Complex_>>>
155 KahanAccumulator(const Complex_& v) : real_(v.real()), imag_(v.imag()) {}
156
157 template <typename Complex_>
159 : real_(v.real_), imag_(v.imag_) {}
160
161 explicit operator Complex() const { return Complex(static_cast<Real>(real_), static_cast<Real>(imag_)); }
162
163 template <typename Complex_,
164 typename = std::enable_if_t<!std::is_floating_point_v<Complex_>>>
165 KahanAccumulator& operator+=(const Complex_& v) {
166 real_ += v.real();
167 imag_ += v.imag();
168 return *this;
169 }
170
171 template <typename Complex_,
172 typename = std::enable_if_t<!std::is_floating_point_v<Complex_>>>
173 KahanAccumulator& operator-=(const Complex_& v) {
174 real_ -= v.real();
175 imag_ -= v.imag();
176 return *this;
177 }
178
179 template <typename Complex_>
181 real_ += v.real();
182 imag_ += v.imag();
183 return *this;
184 }
185
186 template <typename Complex_>
188 real_ -= v.real();
189 imag_ -= v.imag();
190 return *this;
191 }
192
193 template <typename Archive>
194 void serialize(Archive& ar) {
195 ar& real_& imag_;
196 }
197
198private:
199 RealAccumulator real_ = {};
200 RealAccumulator imag_ = {};
201};
202
203} // namespace madness
204
205#endif // MADNESS_MISC_KAHAN_ACCUMULATOR_H_
static const double v
Definition hatom_sf_dirac.cc:20
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
std::ostream & operator<<(std::ostream &os, const particle< PDIM > &p)
Definition lowrankfunction.h:397
std::vector< CCPairFunction< T, NDIM > > operator-(const std::vector< CCPairFunction< T, NDIM > > c1, const std::vector< CCPairFunction< T, NDIM > > &c2)
Definition ccpairfunction.h:1060
double imag(double x)
Definition complexfun.h:56
std::vector< CCPairFunction< T, NDIM > > operator+(const std::vector< CCPairFunction< T, NDIM > > c1, const std::vector< CCPairFunction< T, NDIM > > &c2)
Definition ccpairfunction.h:1052
double real(double x)
Definition complexfun.h:52
Definition mraimpl.h:50
static const double c
Definition relops.cc:10
KahanAccumulator & operator-=(const KahanAccumulator< Complex_ > &v)
Definition kahan_accumulator.h:187
KahanAccumulator(const KahanAccumulator< Complex_ > &v)
Definition kahan_accumulator.h:158
KahanAccumulator & operator+=(const Complex_ &v)
Definition kahan_accumulator.h:165
KahanAccumulator & operator-=(const Complex_ &v)
Definition kahan_accumulator.h:173
KahanAccumulator & operator+=(const KahanAccumulator< Complex_ > &v)
Definition kahan_accumulator.h:180
typename Complex::value_type Real
Definition kahan_accumulator.h:146
KahanAccumulator & operator-=(Real_ v)
Definition kahan_accumulator.h:48
KahanAccumulator & operator+=(Real_ v)
Definition kahan_accumulator.h:38
KahanAccumulator & operator+=(const KahanAccumulator< Real_ > &v)
Definition kahan_accumulator.h:57
KahanAccumulator & operator-=(const KahanAccumulator< Real_ > &v)
Definition kahan_accumulator.h:64
KahanAccumulator operator-() const
Definition kahan_accumulator.h:70
KahanAccumulator(KahanAccumulator< Real_ > v)
Definition kahan_accumulator.h:31
Definition kahan_accumulator.h:14