123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- #ifndef BOOST_HISTOGRAM_ACCUMULATORS_SUM_HPP
- #define BOOST_HISTOGRAM_ACCUMULATORS_SUM_HPP
- #include <boost/core/nvp.hpp>
- #include <boost/histogram/fwd.hpp> // for sum<>
- #include <cmath> // std::abs
- #include <type_traits> // std::is_floating_point, std::common_type
- namespace boost {
- namespace histogram {
- namespace accumulators {
- template <class ValueType>
- class sum {
- static_assert(std::is_floating_point<ValueType>::value,
- "ValueType must be a floating point type");
- public:
- using value_type = ValueType;
- using const_reference = const value_type&;
- sum() = default;
-
- sum(const_reference value) noexcept : sum(value, 0) {}
-
- template <class T>
- sum(const sum<T>& s) noexcept : sum(s.large_part(), s.small_part()) {}
-
- sum(const_reference large_part, const_reference small_part) noexcept
- : large_(large_part), small_(small_part) {}
-
- sum& operator++() noexcept { return operator+=(1); }
-
- sum& operator+=(const_reference value) noexcept {
-
-
- volatile value_type l;
- value_type s;
- if (std::abs(large_) >= std::abs(value)) {
- l = large_;
- s = value;
- } else {
- l = value;
- s = large_;
- }
- large_ += value;
- l = l - large_;
- l = l + s;
- small_ += l;
- return *this;
- }
-
- sum& operator+=(const sum& s) noexcept {
- operator+=(s.large_);
- small_ += s.small_;
- return *this;
- }
-
- sum& operator*=(const_reference value) noexcept {
- large_ *= value;
- small_ *= value;
- return *this;
- }
- bool operator==(const sum& rhs) const noexcept {
- return large_ + small_ == rhs.large_ + rhs.small_;
- }
- bool operator!=(const sum& rhs) const noexcept { return !operator==(rhs); }
-
- value_type value() const noexcept { return large_ + small_; }
-
- const_reference large_part() const noexcept { return large_; }
-
- const_reference small_part() const noexcept { return small_; }
-
-
- explicit operator value_type() const noexcept { return value(); }
- template <class Archive>
- void serialize(Archive& ar, unsigned /* version */) {
- ar& make_nvp("large", large_);
- ar& make_nvp("small", small_);
- }
-
- sum& operator*=(const sum& rhs) noexcept {
- const auto scale = static_cast<value_type>(rhs);
- large_ *= scale;
- small_ *= scale;
- return *this;
- }
- sum operator*(const sum& rhs) const noexcept {
- sum s = *this;
- s *= rhs;
- return s;
- }
- sum& operator/=(const sum& rhs) noexcept {
- const auto scale = 1.0 / static_cast<value_type>(rhs);
- large_ *= scale;
- small_ *= scale;
- return *this;
- }
- sum operator/(const sum& rhs) const noexcept {
- sum s = *this;
- s /= rhs;
- return s;
- }
- bool operator<(const sum& rhs) const noexcept {
- return operator value_type() < rhs.operator value_type();
- }
- bool operator>(const sum& rhs) const noexcept {
- return operator value_type() > rhs.operator value_type();
- }
- bool operator<=(const sum& rhs) const noexcept {
- return operator value_type() <= rhs.operator value_type();
- }
- bool operator>=(const sum& rhs) const noexcept {
- return operator value_type() >= rhs.operator value_type();
- }
-
- private:
- value_type large_{};
- value_type small_{};
- };
- }
- }
- }
- #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
- namespace std {
- template <class T, class U>
- struct common_type<boost::histogram::accumulators::sum<T>,
- boost::histogram::accumulators::sum<U>> {
- using type = boost::histogram::accumulators::sum<common_type_t<T, U>>;
- };
- }
- #endif
- #endif
|