polymorphic_bin.hpp 2.8 KB

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