]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | // Copyright 2018 Hans Dembinski |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. | |
4 | // (See accompanying file LICENSE_1_0.txt | |
5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | ||
7 | #ifndef BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP | |
8 | #define BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP | |
9 | ||
10 | #include <boost/histogram/detail/detect.hpp> | |
11 | #include <type_traits> | |
12 | ||
13 | namespace boost { | |
14 | namespace histogram { | |
15 | namespace axis { | |
16 | ||
17 | /** | |
18 | Holds the bin data of an axis::variant. | |
19 | ||
20 | The interface is a superset of the axis::interval_view | |
21 | class. In addition, the object is implicitly convertible to the value type, | |
22 | returning the equivalent of a call to lower(). For discrete axes, lower() == | |
23 | upper(), and width() returns zero. | |
24 | ||
25 | This is not a view like axis::interval_view for two reasons. | |
26 | - Sequential calls to lower() and upper() would have to each loop through | |
27 | the variant types. This is likely to be slower than filling all the data in | |
28 | one loop. | |
29 | - polymorphic_bin may be created from a temporary instance of axis::variant, | |
30 | like in the call histogram::axis(0). Storing a reference to the axis would | |
31 | result in a dangling reference. Rather than specialing the code to handle | |
32 | this, it seems easier to just use a value instead of a view. | |
33 | */ | |
f67539c2 | 34 | template <class RealType> |
92f5a8d4 TL |
35 | class polymorphic_bin { |
36 | using value_type = RealType; | |
37 | ||
38 | public: | |
39 | polymorphic_bin(value_type lower, value_type upper) | |
40 | : lower_or_value_(lower), upper_(upper) {} | |
41 | ||
42 | /// Implicitly convert to bin value (for axis with discrete values). | |
43 | operator const value_type&() const noexcept { return lower_or_value_; } | |
44 | ||
45 | /// Return lower edge of bin. | |
46 | value_type lower() const noexcept { return lower_or_value_; } | |
47 | /// Return upper edge of bin. | |
48 | value_type upper() const noexcept { return upper_; } | |
49 | /// Return center of bin. | |
50 | value_type center() const noexcept { return 0.5 * (lower() + upper()); } | |
51 | /// Return width of bin. | |
52 | value_type width() const noexcept { return upper() - lower(); } | |
53 | ||
f67539c2 | 54 | template <class BinType> |
92f5a8d4 TL |
55 | bool operator==(const BinType& rhs) const noexcept { |
56 | return equal_impl(detail::has_method_lower<BinType>(), rhs); | |
57 | } | |
58 | ||
f67539c2 | 59 | template <class BinType> |
92f5a8d4 TL |
60 | bool operator!=(const BinType& rhs) const noexcept { |
61 | return !operator==(rhs); | |
62 | } | |
63 | ||
64 | /// Return true if bin is discrete. | |
65 | bool is_discrete() const noexcept { return lower_or_value_ == upper_; } | |
66 | ||
67 | private: | |
68 | bool equal_impl(std::true_type, const polymorphic_bin& rhs) const noexcept { | |
69 | return lower_or_value_ == rhs.lower_or_value_ && upper_ == rhs.upper_; | |
70 | } | |
71 | ||
f67539c2 | 72 | template <class BinType> |
92f5a8d4 TL |
73 | bool equal_impl(std::true_type, const BinType& rhs) const noexcept { |
74 | return lower() == rhs.lower() && upper() == rhs.upper(); | |
75 | } | |
76 | ||
f67539c2 | 77 | template <class BinType> |
92f5a8d4 TL |
78 | bool equal_impl(std::false_type, const BinType& rhs) const noexcept { |
79 | return is_discrete() && static_cast<value_type>(*this) == rhs; | |
80 | } | |
81 | ||
82 | const value_type lower_or_value_, upper_; | |
83 | }; | |
84 | ||
85 | } // namespace axis | |
86 | } // namespace histogram | |
87 | } // namespace boost | |
88 | ||
89 | #endif |