polymorphic_bin.hpp 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. #ifndef BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
  7. #define BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
  8. #include <boost/histogram/detail/meta.hpp>
  9. #include <type_traits>
  10. namespace boost {
  11. namespace histogram {
  12. namespace axis {
  13. /**
  14. Holds the bin data of a axis::variant.
  15. The interface is a superset of the `value_bin_view` and `interval_bin_view`
  16. classes. The methods value() and lower() return the same number. For a value bin,
  17. upper() and lower() and center() return the same number, width() returns zero.
  18. This is not a view like interval_bin_view or value_bin_view for two reasons.
  19. - Sequential calls to lower() and upper() would have to each loop through
  20. the variant types. This is likely to be slower than filling all the data in
  21. one loop.
  22. - polymorphic_bin may be created from a temporary instance of axis::variant,
  23. like in the call histogram::axis(0). Storing a reference to the axis would
  24. result in a dangling reference. Rather than specialing the code to handle
  25. this, it seems easier to just use a value instead of a view here.
  26. */
  27. template <typename RealType>
  28. class polymorphic_bin {
  29. using value_type = RealType;
  30. public:
  31. polymorphic_bin(value_type lower, value_type upper)
  32. : lower_or_value_(lower), upper_(upper) {}
  33. /// Implicitly convert to bin value (for axis with discrete values).
  34. operator const value_type&() const noexcept { return lower_or_value_; }
  35. /// Return lower edge of bin.
  36. value_type lower() const noexcept { return lower_or_value_; }
  37. /// Return upper edge of bin.
  38. value_type upper() const noexcept { return upper_; }
  39. /// Return center of bin.
  40. value_type center() const noexcept { return 0.5 * (lower() + upper()); }
  41. /// Return width of bin.
  42. value_type width() const noexcept { return upper() - lower(); }
  43. template <typename BinType>
  44. bool operator==(const BinType& rhs) const noexcept {
  45. return equal_impl(detail::has_method_lower<BinType>(), rhs);
  46. }
  47. template <typename BinType>
  48. bool operator!=(const BinType& rhs) const noexcept {
  49. return !operator==(rhs);
  50. }
  51. /// Return true if bin is discrete.
  52. bool is_discrete() const noexcept { return lower_or_value_ == upper_; }
  53. private:
  54. bool equal_impl(std::true_type, const polymorphic_bin& rhs) const noexcept {
  55. return lower_or_value_ == rhs.lower_or_value_ && upper_ == rhs.upper_;
  56. }
  57. template <typename BinType>
  58. bool equal_impl(std::true_type, const BinType& rhs) const noexcept {
  59. return lower() == rhs.lower() && upper() == rhs.upper();
  60. }
  61. template <typename BinType>
  62. bool equal_impl(std::false_type, const BinType& rhs) const noexcept {
  63. return is_discrete() && static_cast<value_type>(*this) == rhs;
  64. }
  65. const value_type lower_or_value_, upper_;
  66. };
  67. } // namespace axis
  68. } // namespace histogram
  69. } // namespace boost
  70. #endif