1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- // Copyright 2018 Hans Dembinski
- //
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt
- // or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
- #define BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
- namespace boost {
- namespace histogram {
- namespace axis {
- /**
- Holds the bin data of an axis::variant.
- The interface is a superset of the axis::interval_view
- class. In addition, the object is implicitly convertible to the value type,
- returning the equivalent of a call to lower(). For discrete axes, lower() ==
- upper(), and width() returns zero.
- This is not a view like axis::interval_view for two reasons.
- - Sequential calls to lower() and upper() would have to each loop through
- the variant types. This is likely to be slower than filling all the data in
- one loop.
- - polymorphic_bin may be created from a temporary instance of axis::variant,
- like in the call histogram::axis(0). Storing a reference to the axis would
- result in a dangling reference. Rather than specialing the code to handle
- this, it seems easier to just use a value instead of a view.
- */
- template <class RealType>
- class polymorphic_bin {
- using value_type = RealType;
- public:
- polymorphic_bin(value_type lower, value_type upper)
- : lower_or_value_(lower), upper_(upper) {}
- /// Implicitly convert to bin value (for axis with discrete values).
- operator const value_type&() const noexcept { return lower_or_value_; }
- /// Return lower edge of bin.
- value_type lower() const noexcept { return lower_or_value_; }
- /// Return upper edge of bin.
- value_type upper() const noexcept { return upper_; }
- /// Return center of bin.
- value_type center() const noexcept { return 0.5 * (lower() + upper()); }
- /// Return width of bin.
- value_type width() const noexcept { return upper() - lower(); }
- template <class BinType>
- bool operator==(const BinType& rhs) const noexcept {
- return equal_impl(rhs, 0);
- }
- template <class BinType>
- bool operator!=(const BinType& rhs) const noexcept {
- return !operator==(rhs);
- }
- /// Return true if bin is discrete.
- bool is_discrete() const noexcept { return lower_or_value_ == upper_; }
- private:
- bool equal_impl(const polymorphic_bin& rhs, int) const noexcept {
- return lower_or_value_ == rhs.lower_or_value_ && upper_ == rhs.upper_;
- }
- template <class BinType>
- auto equal_impl(const BinType& rhs, decltype(rhs.lower(), 0)) const noexcept {
- return lower() == rhs.lower() && upper() == rhs.upper();
- }
- template <class BinType>
- bool equal_impl(const BinType& rhs, float) const noexcept {
- return is_discrete() && static_cast<value_type>(*this) == rhs;
- }
- const value_type lower_or_value_, upper_;
- };
- } // namespace axis
- } // namespace histogram
- } // namespace boost
- #endif
|