/builds/MusicScience37Projects/numerical-analysis/numerical-collection-cpp/include/num_collect/util/kahan_adder.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2021 MusicScience37 (Kenta Kabashima) |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | /*! |
17 | | * \file |
18 | | * \brief Definition of kahan_adder class. |
19 | | */ |
20 | | #pragma once |
21 | | |
22 | | #include "num_collect/util/concepts/kahan_addable.h" |
23 | | |
24 | | namespace num_collect::util { |
25 | | |
26 | | /*! |
27 | | * \brief Class to add numbers using Kahan summation \cite Kahan1965. |
28 | | * |
29 | | * \tparam T Type of numbers. |
30 | | */ |
31 | | template <concepts::kahan_addable T> |
32 | | class kahan_adder { |
33 | | public: |
34 | | /*! |
35 | | * \brief Constructor. |
36 | | * |
37 | | * \note This won't work for Eigen's vectors and matrices. |
38 | | * Use another constructor for them. |
39 | | */ |
40 | 36 | kahan_adder() : kahan_adder(static_cast<T>(0)) {} _ZN11num_collect4util11kahan_adderIfEC2Ev Line | Count | Source | 40 | 16 | kahan_adder() : kahan_adder(static_cast<T>(0)) {} |
_ZN11num_collect4util11kahan_adderINSt3__17complexIfEEEC2Ev Line | Count | Source | 40 | 2 | kahan_adder() : kahan_adder(static_cast<T>(0)) {} |
_ZN11num_collect4util11kahan_adderIdEC2Ev Line | Count | Source | 40 | 16 | kahan_adder() : kahan_adder(static_cast<T>(0)) {} |
_ZN11num_collect4util11kahan_adderINSt3__17complexIdEEEC2Ev Line | Count | Source | 40 | 2 | kahan_adder() : kahan_adder(static_cast<T>(0)) {} |
|
41 | | |
42 | | /*! |
43 | | * \brief Construct with zero number. |
44 | | * |
45 | | * This constructor is useful for Eigen's vectors and matrices. |
46 | | * |
47 | | * \param[in] zero Zero. |
48 | | */ |
49 | | explicit kahan_adder(const T& zero) |
50 | 36 | : sum_(zero), rem_(zero), prev_sum_(zero) {} _ZN11num_collect4util11kahan_adderINSt3__17complexIfEEEC2ERKS4_ Line | Count | Source | 50 | 2 | : sum_(zero), rem_(zero), prev_sum_(zero) {} |
_ZN11num_collect4util11kahan_adderINSt3__17complexIdEEEC2ERKS4_ Line | Count | Source | 50 | 2 | : sum_(zero), rem_(zero), prev_sum_(zero) {} |
_ZN11num_collect4util11kahan_adderIfEC2ERKf Line | Count | Source | 50 | 16 | : sum_(zero), rem_(zero), prev_sum_(zero) {} |
_ZN11num_collect4util11kahan_adderIdEC2ERKd Line | Count | Source | 50 | 16 | : sum_(zero), rem_(zero), prev_sum_(zero) {} |
|
51 | | |
52 | | /*! |
53 | | * \brief Add a number. |
54 | | * |
55 | | * \param[in] value Added value. |
56 | | * \return This. |
57 | | */ |
58 | 21.0k | auto add(const T& value) -> kahan_adder& { |
59 | 21.0k | prev_sum_ = sum_; |
60 | 21.0k | rem_ += value; |
61 | 21.0k | sum_ += rem_; |
62 | 21.0k | rem_ -= sum_ - prev_sum_; |
63 | 21.0k | return *this; |
64 | 21.0k | } _ZN11num_collect4util11kahan_adderIfE3addERKf Line | Count | Source | 58 | 10.4k | auto add(const T& value) -> kahan_adder& { | 59 | 10.4k | prev_sum_ = sum_; | 60 | 10.4k | rem_ += value; | 61 | 10.4k | sum_ += rem_; | 62 | 10.4k | rem_ -= sum_ - prev_sum_; | 63 | 10.4k | return *this; | 64 | 10.4k | } |
_ZN11num_collect4util11kahan_adderINSt3__17complexIfEEE3addERKS4_ Line | Count | Source | 58 | 82 | auto add(const T& value) -> kahan_adder& { | 59 | 82 | prev_sum_ = sum_; | 60 | 82 | rem_ += value; | 61 | 82 | sum_ += rem_; | 62 | 82 | rem_ -= sum_ - prev_sum_; | 63 | 82 | return *this; | 64 | 82 | } |
_ZN11num_collect4util11kahan_adderIdE3addERKd Line | Count | Source | 58 | 10.4k | auto add(const T& value) -> kahan_adder& { | 59 | 10.4k | prev_sum_ = sum_; | 60 | 10.4k | rem_ += value; | 61 | 10.4k | sum_ += rem_; | 62 | 10.4k | rem_ -= sum_ - prev_sum_; | 63 | 10.4k | return *this; | 64 | 10.4k | } |
_ZN11num_collect4util11kahan_adderINSt3__17complexIdEEE3addERKS4_ Line | Count | Source | 58 | 82 | auto add(const T& value) -> kahan_adder& { | 59 | 82 | prev_sum_ = sum_; | 60 | 82 | rem_ += value; | 61 | 82 | sum_ += rem_; | 62 | 82 | rem_ -= sum_ - prev_sum_; | 63 | 82 | return *this; | 64 | 82 | } |
|
65 | | |
66 | | /*! |
67 | | * \brief Subtract a number. |
68 | | * |
69 | | * \param[in] value Added value. |
70 | | * \return This. |
71 | | */ |
72 | 4 | auto sub(const T& value) -> kahan_adder& { |
73 | 4 | prev_sum_ = sum_; |
74 | 4 | rem_ += -value; |
75 | 4 | sum_ += rem_; |
76 | 4 | rem_ -= sum_ - prev_sum_; |
77 | 4 | return *this; |
78 | 4 | } _ZN11num_collect4util11kahan_adderIfE3subERKf Line | Count | Source | 72 | 2 | auto sub(const T& value) -> kahan_adder& { | 73 | 2 | prev_sum_ = sum_; | 74 | 2 | rem_ += -value; | 75 | 2 | sum_ += rem_; | 76 | 2 | rem_ -= sum_ - prev_sum_; | 77 | 2 | return *this; | 78 | 2 | } |
_ZN11num_collect4util11kahan_adderIdE3subERKd Line | Count | Source | 72 | 2 | auto sub(const T& value) -> kahan_adder& { | 73 | 2 | prev_sum_ = sum_; | 74 | 2 | rem_ += -value; | 75 | 2 | sum_ += rem_; | 76 | 2 | rem_ -= sum_ - prev_sum_; | 77 | 2 | return *this; | 78 | 2 | } |
|
79 | | |
80 | | /*! |
81 | | * \brief Add a number. |
82 | | * |
83 | | * \param[in] value Added value. |
84 | | * \return This. |
85 | | */ |
86 | 21.0k | auto operator+=(const T& value) -> kahan_adder& { |
87 | 21.0k | add(value); |
88 | 21.0k | return *this; |
89 | 21.0k | } _ZN11num_collect4util11kahan_adderIfEpLERKf Line | Count | Source | 86 | 10.4k | auto operator+=(const T& value) -> kahan_adder& { | 87 | 10.4k | add(value); | 88 | 10.4k | return *this; | 89 | 10.4k | } |
_ZN11num_collect4util11kahan_adderINSt3__17complexIfEEEpLERKS4_ Line | Count | Source | 86 | 82 | auto operator+=(const T& value) -> kahan_adder& { | 87 | 82 | add(value); | 88 | 82 | return *this; | 89 | 82 | } |
_ZN11num_collect4util11kahan_adderIdEpLERKd Line | Count | Source | 86 | 10.4k | auto operator+=(const T& value) -> kahan_adder& { | 87 | 10.4k | add(value); | 88 | 10.4k | return *this; | 89 | 10.4k | } |
_ZN11num_collect4util11kahan_adderINSt3__17complexIdEEEpLERKS4_ Line | Count | Source | 86 | 82 | auto operator+=(const T& value) -> kahan_adder& { | 87 | 82 | add(value); | 88 | 82 | return *this; | 89 | 82 | } |
|
90 | | |
91 | | /*! |
92 | | * \brief Subtract a number. |
93 | | * |
94 | | * \param[in] value Added value. |
95 | | * \return This. |
96 | | */ |
97 | 4 | auto operator-=(const T& value) -> kahan_adder& { |
98 | 4 | sub(value); |
99 | 4 | return *this; |
100 | 4 | } _ZN11num_collect4util11kahan_adderIfEmIERKf Line | Count | Source | 97 | 2 | auto operator-=(const T& value) -> kahan_adder& { | 98 | 2 | sub(value); | 99 | 2 | return *this; | 100 | 2 | } |
_ZN11num_collect4util11kahan_adderIdEmIERKd Line | Count | Source | 97 | 2 | auto operator-=(const T& value) -> kahan_adder& { | 98 | 2 | sub(value); | 99 | 2 | return *this; | 100 | 2 | } |
|
101 | | |
102 | | /*! |
103 | | * \brief Get sum. |
104 | | * |
105 | | * \return Sum. |
106 | | */ |
107 | 36 | [[nodiscard]] auto sum() const noexcept -> const T& { return sum_; } _ZNK11num_collect4util11kahan_adderIfE3sumEv Line | Count | Source | 107 | 16 | [[nodiscard]] auto sum() const noexcept -> const T& { return sum_; } |
_ZNK11num_collect4util11kahan_adderINSt3__17complexIfEEE3sumEv Line | Count | Source | 107 | 2 | [[nodiscard]] auto sum() const noexcept -> const T& { return sum_; } |
_ZNK11num_collect4util11kahan_adderIdE3sumEv Line | Count | Source | 107 | 16 | [[nodiscard]] auto sum() const noexcept -> const T& { return sum_; } |
_ZNK11num_collect4util11kahan_adderINSt3__17complexIdEEE3sumEv Line | Count | Source | 107 | 2 | [[nodiscard]] auto sum() const noexcept -> const T& { return sum_; } |
|
108 | | |
109 | | /*! |
110 | | * \brief Get sum. |
111 | | * |
112 | | * \return Sum. |
113 | | */ |
114 | | operator T() const { // NOLINT: Allow implicit conversion. |
115 | | return sum_; |
116 | | } |
117 | | |
118 | | private: |
119 | | //! Sum. |
120 | | T sum_; |
121 | | |
122 | | //! Remaining. |
123 | | T rem_; |
124 | | |
125 | | //! Previous sum. |
126 | | T prev_sum_; |
127 | | }; |
128 | | |
129 | | } // namespace num_collect::util |