Scippy

SoPlex

Sequential object-oriented simPlex

stablesum.h
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2022 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 #ifndef _SOPLEX_STABLE_SUM_H_
17 #define _SOPLEX_STABLE_SUM_H_
18 #include <type_traits>
19 
20 // #define CHECK_STABLESUM // double check the stable sum computation
21 
22 namespace soplex
23 {
24 
25 template <typename T>
26 class StableSum
27 {
28  typename std::remove_const<T>::type sum;
29 
30 public:
31  StableSum() : sum(0) {}
32  StableSum(const T& init) : sum(init) {}
33 
34  void operator+=(const T& input)
35  {
36  sum += input;
37  }
38 
39  void operator-=(const T& input)
40  {
41  sum -= input;
42  }
43 
44  operator typename std::remove_const<T>::type() const
45  {
46  return sum;
47  }
48 
49 };
50 
51 template <>
52 class StableSum<double>
53 {
54  double sum = 0;
55  double c = 0;
56 #ifdef CHECK_STABLESUM
57  double checksum = 0;
58 #endif
59 
60 public:
61  StableSum() = default;
62  StableSum(double init) : sum(init), c(0) {}
63 
64  void operator+=(double input)
65  {
66 #if defined(_MSC_VER) || defined(__INTEL_COMPILER)
67 #pragma float_control( precise, on )
68 #endif
69 #ifdef CHECK_STABLESUM
70  checksum += input;
71 #endif
72  double t = sum + input;
73  double z = t - sum;
74  double y = (sum - (t - z)) + (input - z);
75  c += y;
76 
77  sum = t;
78  }
79 
80  void operator-=(double input)
81  {
82  (*this) += -input;
83  }
84 
85  operator double() const
86  {
87 #ifdef CHECK_STABLESUM
88 
89  if(spxAbs(checksum - (sum + c)) >= 1e-6)
90  printf("stablesum viol: %g, rel: %g, checksum: %g\n", spxAbs(checksum - (sum + c)),
91  spxAbs(checksum - (sum + c)) / MAXIMUM(1.0, MAXIMUM(spxAbs(checksum), spxAbs(sum + c))), checksum);
92 
93  assert(spxAbs(checksum - (sum + c)) < 1e-6);
94 #endif
95  return sum + c;
96  }
97 };
98 
99 /// Output operator.
100 template < class T >
101 std::ostream& operator<<(std::ostream& s, const StableSum<T>& sum)
102 {
103  s << static_cast<T>(sum);
104 
105  return s;
106 }
107 
108 }
109 
110 #endif
void operator+=(double input)
Definition: stablesum.h:64
void operator-=(double input)
Definition: stablesum.h:80
#define MAXIMUM(x, y)
Definition: spxdefines.h:284
void operator+=(const T &input)
Definition: stablesum.h:34
Everything should be within this namespace.
std::remove_const< T >::type sum
Definition: stablesum.h:28
R spxAbs(R a)
Definition: spxdefines.h:338
void operator-=(const T &input)
Definition: stablesum.h:39
StableSum(const T &init)
Definition: stablesum.h:32