/* * © 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 template 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& 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