106 lines
1.8 KiB
C++
106 lines
1.8 KiB
C++
/*
|
||
* © Copyright 2014 – Urheberrechtshinweis
|
||
* Alle Rechte vorbehalten / All Rights Reserved
|
||
*
|
||
* Programmcode ist urheberrechtlich geschuetzt.
|
||
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
|
||
* Keine Verwendung ohne explizite Genehmigung.
|
||
* (vgl. § 106 ff UrhG / § 97 UrhG)
|
||
*/
|
||
|
||
#ifndef KAHANSUM_H
|
||
#define KAHANSUM_H
|
||
|
||
#include <vector>
|
||
|
||
template <typename T> class KahanSum {
|
||
|
||
private:
|
||
|
||
const T zero;
|
||
|
||
/** current sum */
|
||
T sum;
|
||
|
||
/** current compensation */
|
||
T comp;
|
||
|
||
|
||
public:
|
||
|
||
/** ctor with zero element */
|
||
KahanSum(const T zero) : zero(zero), sum(zero), comp(zero) {
|
||
|
||
}
|
||
|
||
KahanSum& operator += (const T val) {
|
||
add(val);
|
||
return *this;
|
||
}
|
||
|
||
KahanSum& operator -= (const T val) {
|
||
sub(val);
|
||
return *this;
|
||
}
|
||
|
||
T get() const {
|
||
return sum;
|
||
}
|
||
|
||
private:
|
||
|
||
#ifdef _MSC_VER
|
||
#pragma optimize( "", off )
|
||
#else
|
||
#pragma GCC push_options
|
||
#pragma GCC optimize ("O0")
|
||
#endif
|
||
|
||
/** adjust the sum */
|
||
void add(const T val) {
|
||
const T y = val - comp;
|
||
const T t = sum + y;
|
||
comp = (t-sum) - y; // very important line
|
||
sum = t;
|
||
}
|
||
|
||
/** adjust the sum */
|
||
void sub(const T val) {
|
||
const T y = val - comp;
|
||
const T t = sum - y;
|
||
comp = (t-sum) + y; // very important line
|
||
sum = t;
|
||
}
|
||
|
||
#ifdef _MSC_VER
|
||
#pragma optimize( "", on )
|
||
#else
|
||
#pragma GCC pop_options
|
||
#endif
|
||
|
||
public:
|
||
|
||
static T get(const std::vector<T>& values, const T zero = T()) {
|
||
return get(values.data(), values.size(), zero);
|
||
}
|
||
|
||
static T get(const T* values, const size_t cnt, const T zero = T()) {
|
||
|
||
T sum = zero;
|
||
volatile T comp = zero;
|
||
for (size_t i = 0; i < cnt; ++i) {
|
||
const T inp = values[i];
|
||
const volatile T y = inp - comp;
|
||
const volatile T t = sum + y;
|
||
comp = (t-sum) - y;
|
||
sum = t;
|
||
}
|
||
|
||
return sum;
|
||
|
||
}
|
||
|
||
};
|
||
|
||
#endif // KAHANSUM_H
|