Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Add option to provide an initial value in KahanSum
  • Loading branch information
xvallspl committed Apr 6, 2017
commit 020dcdb860a80cb8045332976c795c2a16b084c4
27 changes: 17 additions & 10 deletions math/mathcore/inc/Math/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ namespace ROOT {
/// by adding a sequence of finite precision floating point numbers.
/// This is done by keeping a separate running compensation (a variable to accumulate small errors).\n
///
/// The intial values of the result and the correction are set to the default value of the type it hass been instantiated with.\n
/// The intial values of the result and the correction are set to the default value of the type it hass been
/// instantiated with.\n
/// ####Examples:
/// ~~~{.cpp}
/// std::vector<double> numbers = {0.01, 0.001, 0.0001, 0.000001, 0.00000000001};
Expand All @@ -83,6 +84,9 @@ namespace ROOT {
template <class T>
class KahanSum {
public:
/// Constructor accepting a initial value for the summation as parameter
KahanSum(const T &initialValue = T{}) : fSum(initialValue) {}

/// Single element accumulated addition.
void Add(const T &x)
{
Expand All @@ -93,19 +97,22 @@ namespace ROOT {
}

/// Iterate over a datastructure referenced by a pointer and accumulate on the exising result
template<class Iterator>
template <class Iterator>
void Add(const Iterator begin, const Iterator end)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xvallspl, @lmoneta : is it really better to have begin and end here? Can't we pass something to iterate on? With range based looping this would not imply any code change in the body of the methods.

{
static_assert(!std::is_same<decltype(*begin), T>::value, "Iterator points to an element of the different type than the KahanSum class");
for( auto it = begin; it!=end; it++ ) this->Add(*it);
{
static_assert(!std::is_same<decltype(*begin), T>::value,
"Iterator points to an element of the different type than the KahanSum class");
for (auto it = begin; it != end; it++) this->Add(*it);
}

/// Iterate over a datastructure referenced by a pointer and return the result of its accumulation
template<class Iterator>
static T Accumulate(const Iterator begin, const Iterator end)
/// Iterate over a datastructure referenced by a pointer and return the result of its accumulation.
/// Can take an initial value as third parameter.
template <class Iterator>
static T Accumulate(const Iterator begin, const Iterator end, const T &initialValue = T{})
{
static_assert(!std::is_same<decltype(*begin), T>::value, "Iterator points to an element of the different type than the KahanSum class");
KahanSum init;
static_assert(!std::is_same<decltype(*begin), T>::value,
"Iterator points to an element of the different type than the KahanSum class");
KahanSum init(initialValue);
init.Add(begin, end);
return init.fSum;
}
Expand Down
8 changes: 8 additions & 0 deletions math/mathcore/test/testKahan.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ int KahanTest()
k.Add(numbers.begin(), numbers.end());
auto result = ROOT::Math::KahanSum<double>::Accumulate(numbers.begin(), numbers.end());
if (k.Result() != result) return 1;

ROOT::Math::KahanSum<double> k2;
ROOT::Math::KahanSum<double> k3(1);
k2.Add(1);
k2.Add(numbers.begin(), numbers.end());
k3.Add(numbers.begin(), numbers.end());
if (k2.Result() != k3.Result()) return 2;

return 0;
}

Expand Down