diff --git a/include/boost/histogram/axis.hpp b/include/boost/histogram/axis.hpp index 9bd923fc..2aabeff5 100644 --- a/include/boost/histogram/axis.hpp +++ b/include/boost/histogram/axis.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -127,7 +126,7 @@ protected: return *this; } - bool operator==(const axis_base &rhs) const { + bool operator==(const axis_base &rhs) const noexcept { return size_ == rhs.size_ && label_ == rhs.label_; } @@ -167,7 +166,7 @@ protected: return *this; } - bool operator==(const axis_base_uoflow &rhs) const { + bool operator==(const axis_base_uoflow &rhs) const noexcept { return axis_base::operator==(rhs) && shape_ == rhs.shape_; } @@ -182,28 +181,28 @@ namespace transform { struct identity { template static T forward(T v) { return v; } template static T inverse(T v) { return v; } - bool operator==(const identity &) const { return true; } + bool operator==(const identity &) const noexcept { return true; } template void serialize(Archive &, unsigned) {} }; struct log { template static T forward(T v) { return std::log(v); } template static T inverse(T v) { return std::exp(v); } - bool operator==(const log &) const { return true; } + bool operator==(const log &) const noexcept { return true; } template void serialize(Archive &, unsigned) {} }; struct sqrt { template static T forward(T v) { return std::sqrt(v); } template static T inverse(T v) { return v * v; } - bool operator==(const sqrt &) const { return true; } + bool operator==(const sqrt &) const noexcept { return true; } template void serialize(Archive &, unsigned) {} }; struct cos { template static T forward(T v) { return std::cos(v); } template static T inverse(T v) { return std::acos(v); } - bool operator==(const cos &) const { return true; } + bool operator==(const cos &) const noexcept { return true; } template void serialize(Archive &, unsigned) {} }; @@ -215,7 +214,7 @@ struct pow { return std::pow(v, 1.0 / value); } double value = 1.0; - bool operator==(const pow &other) const { return value == other.value; } + bool operator==(const pow &other) const noexcept { return value == other.value; } template void serialize(Archive &, unsigned); }; } // namespace transform @@ -226,8 +225,7 @@ struct pow { * Very fast. Binning is a O(1) operation. */ template -class regular : public axis_base_uoflow, Transform, - boost::operators> { +class regular : public axis_base_uoflow, Transform { public: using value_type = RealType; using bin_type = interval; @@ -315,7 +313,7 @@ private: * bins for this axis. Binning is a O(1) operation. */ template -class circular : public axis_base, boost::operators> { +class circular : public axis_base { public: using value_type = RealType; using bin_type = interval; @@ -355,7 +353,7 @@ public: return {eval(idx), eval(idx + 1)}; } - bool operator==(const circular &o) const { + bool operator==(const circular &o) const noexcept { return axis_base::operator==(o) && phase_ == o.phase_ && perimeter_ == o.perimeter_; } @@ -380,7 +378,7 @@ private: * and the problem domain allows it, prefer a regular. */ template -class variable : public axis_base_uoflow, boost::operators> { +class variable : public axis_base_uoflow { public: using value_type = RealType; using bin_type = interval; @@ -448,7 +446,7 @@ public: return {eval(idx), eval(idx + 1)}; } - bool operator==(const variable &o) const { + bool operator==(const variable &o) const noexcept { if (!axis_base_uoflow::operator==(o)) { return false; } @@ -476,7 +474,7 @@ private: * faster than a regular. */ template -class integer : public axis_base_uoflow, boost::operators> { +class integer : public axis_base_uoflow { public: using value_type = IntType; using bin_type = interval; @@ -510,7 +508,7 @@ public: /// Returns the integer that is mapped to the bin index. bin_type operator[](int idx) const { return {min_ + idx, min_ + idx + 1}; } - bool operator==(const integer &o) const { + bool operator==(const integer &o) const noexcept { return axis_base_uoflow::operator==(o) && min_ == o.min_; } @@ -537,7 +535,7 @@ private: * Binning is a O(1) operation. The value type must be hashable. */ template -class category : public axis_base, boost::operators> { +class category : public axis_base { using map_type = bimap; public: @@ -597,9 +595,9 @@ public: return it->second; } - bool operator==(const category &other) const { - return axis_base::operator==(other) && - std::equal(map_->begin(), map_->end(), other.map_->begin()); + bool operator==(const category &o) const noexcept { + return axis_base::operator==(o) && + std::equal(map_->begin(), map_->end(), o.map_->begin()); } const_iterator begin() const { return const_iterator(*this, 0); } diff --git a/include/boost/histogram/detail/meta.hpp b/include/boost/histogram/detail/meta.hpp index 86c181b4..3299c0e3 100644 --- a/include/boost/histogram/detail/meta.hpp +++ b/include/boost/histogram/detail/meta.hpp @@ -43,13 +43,16 @@ template ()), std::end(std::declval()))> struct is_sequence {}; -template struct combine { +template struct combiner { using type = typename mpl::copy_if>, mpl::back_inserter>::type; }; +template +using combine = typename combiner::type; + struct bool_mask_op { std::vector &b; bool v; diff --git a/include/boost/histogram/histogram_fwd.hpp b/include/boost/histogram/histogram_fwd.hpp index 08684784..f69127a0 100644 --- a/include/boost/histogram/histogram_fwd.hpp +++ b/include/boost/histogram/histogram_fwd.hpp @@ -65,6 +65,47 @@ inline detail::keep_dynamic keep(unsigned i, Rest... rest) { return s; } +// fast operators (boost::operators does not use rvalue references yet) +template +histogram && operator+(histogram &&a, + const histogram &b) +{ a+=b; return std::move(a); } + +template +histogram&& operator+(histogram &&a, + histogram &&b) +{ a+=b; return std::move(a); } + +template +histogram&& operator+(const histogram &a, + histogram &&b) +{ b+=a; return std::move(b); } + +template +histogram operator+(const histogram &a, + const histogram &b) +{ histogram r(a); r+=b; return r; } + +template +histogram&& operator*(histogram &&a, + const double x) +{ a*=x; return std::move(a); } + +template +histogram&& operator*(const double x, + histogram &&b) +{ b*=x; return std::move(b); } + +template +histogram operator*(const histogram &a, + const double x) +{ histogram r(a); r*=x; return r; } + +template +histogram operator*(const double x, + const histogram &b) +{ histogram r(b); r*=x; return r; } + } // namespace histogram } // namespace boost diff --git a/include/boost/histogram/histogram_impl_dynamic.hpp b/include/boost/histogram/histogram_impl_dynamic.hpp index f7d69c7a..099328e8 100644 --- a/include/boost/histogram/histogram_impl_dynamic.hpp +++ b/include/boost/histogram/histogram_impl_dynamic.hpp @@ -431,22 +431,22 @@ private: template inline histogram< - Dynamic, typename detail::combine>::type> + Dynamic, detail::combine>> make_dynamic_histogram(Axes &&... axes) { - return histogram>::type>( + return histogram>>( std::forward(axes)...); } template inline histogram< - Dynamic, typename detail::combine>::type, + Dynamic, detail::combine>, Storage> make_dynamic_histogram_with(Axes &&... axes) { return histogram< Dynamic, - typename detail::combine>::type, + detail::combine>, Storage>(std::forward(axes)...); } diff --git a/include/boost/histogram/histogram_impl_static.hpp b/include/boost/histogram/histogram_impl_static.hpp index e2072a59..ab580920 100644 --- a/include/boost/histogram/histogram_impl_static.hpp +++ b/include/boost/histogram/histogram_impl_static.hpp @@ -7,8 +7,6 @@ #ifndef _BOOST_HISTOGRAM_HISTOGRAM_IMPL_STATIC_HPP_ #define _BOOST_HISTOGRAM_HISTOGRAM_IMPL_STATIC_HPP_ -#include -#include #include #include #include diff --git a/test/histogram_test.cpp b/test/histogram_test.cpp index fda71217..9cd74537 100644 --- a/test/histogram_test.cpp +++ b/test/histogram_test.cpp @@ -532,6 +532,32 @@ template void run_tests() { BOOST_TEST_EQ(h.sum(), 20.0); } + // operators + { + auto a = make_histogram(Type(), axis::integer<>(0, 3)); + auto b = a; + a.fill(0); + b.fill(1); + auto c = a + b; + BOOST_TEST_EQ(c.value(0), 1.0); + BOOST_TEST_EQ(c.value(1), 1.0); + c += b; + BOOST_TEST_EQ(c.value(0), 1.0); + BOOST_TEST_EQ(c.value(1), 2.0); + auto d = 3 * a; + auto e = b * 2; + BOOST_TEST_EQ(d.value(0), 3.0); + BOOST_TEST_EQ(d.value(1), 0.0); + BOOST_TEST_EQ(e.value(0), 0.0); + BOOST_TEST_EQ(e.value(1), 2.0); + auto r = a; + r += b; + r += d; + BOOST_TEST_EQ(r.value(0), 4.0); + BOOST_TEST_EQ(r.value(1), 1.0); + BOOST_TEST_EQ(r, a + b + 3 * a); + } + // histogram_serialization { enum { A, B, C }; @@ -679,7 +705,7 @@ template void run_mixed_tests() { { auto a = make_histogram(T1{}, axis::regular<>{3, 0, 3}, axis::integer<>(0, 2)); - auto b = make_histogram(T2{}, axis::regular<>{3, 0, 3}, + auto b = make_histogram>(T2{}, axis::regular<>{3, 0, 3}, axis::integer<>(0, 2)); BOOST_TEST_EQ(a, b); auto b2 = make_histogram(T2{}, axis::integer<>{0, 3}, @@ -694,7 +720,7 @@ template void run_mixed_tests() { { auto a = make_histogram(T1{}, axis::regular<>{3, 0, 3}, axis::integer<>(0, 2)); - auto b = make_histogram(T2{}, axis::regular<>{3, 0, 3}, + auto b = make_histogram>(T2{}, axis::regular<>{3, 0, 3}, axis::integer<>(0, 2)); a.fill(1, 1); BOOST_TEST_NE(a, b);