File indexing completed on 2025-01-18 09:38:09
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_HISTOGRAM_ACCUMULATORS_SUM_HPP
0008 #define BOOST_HISTOGRAM_ACCUMULATORS_SUM_HPP
0009
0010 #include <boost/core/nvp.hpp>
0011 #include <boost/histogram/fwd.hpp> // for sum<>
0012 #include <cmath> // std::abs
0013 #include <type_traits> // std::is_floating_point, std::common_type
0014
0015 namespace boost {
0016 namespace histogram {
0017 namespace accumulators {
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 template <class ValueType>
0031 class sum {
0032 static_assert(std::is_floating_point<ValueType>::value,
0033 "ValueType must be a floating point type");
0034
0035 public:
0036 using value_type = ValueType;
0037 using const_reference = const value_type&;
0038
0039 sum() = default;
0040
0041
0042 sum(const_reference value) noexcept : sum(value, 0) {}
0043
0044
0045 template <class T>
0046 sum(const sum<T>& s) noexcept : sum(s.large_part(), s.small_part()) {}
0047
0048
0049 sum(const_reference large_part, const_reference small_part) noexcept
0050 : large_(large_part), small_(small_part) {}
0051
0052
0053 sum& operator++() noexcept { return operator+=(1); }
0054
0055
0056 sum& operator+=(const_reference value) noexcept {
0057
0058
0059 volatile value_type l;
0060 value_type s;
0061 if (std::abs(large_) >= std::abs(value)) {
0062 l = large_;
0063 s = value;
0064 } else {
0065 l = value;
0066 s = large_;
0067 }
0068 large_ += value;
0069 l = l - large_;
0070 l = l + s;
0071 small_ += l;
0072 return *this;
0073 }
0074
0075
0076 sum& operator+=(const sum& s) noexcept {
0077 operator+=(s.large_);
0078 small_ += s.small_;
0079 return *this;
0080 }
0081
0082
0083 sum& operator*=(const_reference value) noexcept {
0084 large_ *= value;
0085 small_ *= value;
0086 return *this;
0087 }
0088
0089 bool operator==(const sum& rhs) const noexcept {
0090 return large_ + small_ == rhs.large_ + rhs.small_;
0091 }
0092
0093 bool operator!=(const sum& rhs) const noexcept { return !operator==(rhs); }
0094
0095
0096 value_type value() const noexcept { return large_ + small_; }
0097
0098
0099 const_reference large_part() const noexcept { return large_; }
0100
0101
0102 const_reference small_part() const noexcept { return small_; }
0103
0104
0105
0106 explicit operator value_type() const noexcept { return value(); }
0107
0108 template <class Archive>
0109 void serialize(Archive& ar, unsigned ) {
0110 ar& make_nvp("large", large_);
0111 ar& make_nvp("small", small_);
0112 }
0113
0114
0115
0116 sum& operator*=(const sum& rhs) noexcept {
0117 const auto scale = static_cast<value_type>(rhs);
0118 large_ *= scale;
0119 small_ *= scale;
0120 return *this;
0121 }
0122
0123 sum operator*(const sum& rhs) const noexcept {
0124 sum s = *this;
0125 s *= rhs;
0126 return s;
0127 }
0128
0129 sum& operator/=(const sum& rhs) noexcept {
0130 const auto scale = 1.0 / static_cast<value_type>(rhs);
0131 large_ *= scale;
0132 small_ *= scale;
0133 return *this;
0134 }
0135
0136 sum operator/(const sum& rhs) const noexcept {
0137 sum s = *this;
0138 s /= rhs;
0139 return s;
0140 }
0141
0142 bool operator<(const sum& rhs) const noexcept {
0143 return operator value_type() < rhs.operator value_type();
0144 }
0145
0146 bool operator>(const sum& rhs) const noexcept {
0147 return operator value_type() > rhs.operator value_type();
0148 }
0149
0150 bool operator<=(const sum& rhs) const noexcept {
0151 return operator value_type() <= rhs.operator value_type();
0152 }
0153
0154 bool operator>=(const sum& rhs) const noexcept {
0155 return operator value_type() >= rhs.operator value_type();
0156 }
0157
0158
0159
0160 private:
0161 value_type large_{};
0162 value_type small_{};
0163 };
0164
0165 }
0166 }
0167 }
0168
0169 #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
0170 namespace std {
0171 template <class T, class U>
0172 struct common_type<boost::histogram::accumulators::sum<T>,
0173 boost::histogram::accumulators::sum<U>> {
0174 using type = boost::histogram::accumulators::sum<common_type_t<T, U>>;
0175 };
0176 }
0177 #endif
0178
0179 #endif