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