diff --git a/include/boost/histogram/axis/category.hpp b/include/boost/histogram/axis/category.hpp index 15c4a9b5..f54b5c40 100644 --- a/include/boost/histogram/axis/category.hpp +++ b/include/boost/histogram/axis/category.hpp @@ -97,7 +97,7 @@ public: /** Construct axis from an initializer list of unique values. * - * \param list std::initializer_list of unique values. + * \param list `std::initializer_list` of unique values. * \param meta description of the axis. * \param alloc allocator instance to use. */ @@ -106,30 +106,33 @@ public: allocator_type alloc = {}) : category(list.begin(), list.end(), std::move(meta), std::move(alloc)) {} - /// Returns the bin index for the passed argument. - int operator()(const value_type& x) const noexcept { + /// Return index for value argument. + index_type operator()(const value_type& x) const noexcept { const auto beg = vec_meta_.first().begin(); const auto end = vec_meta_.first().end(); return std::distance(beg, std::find(beg, end, x)); } - /// Returns the value for the bin index (performs a range check). - decltype(auto) value(int idx) const { + /// Return value for index argument. + /// Throws `std::out_of_range` if the index is out of bounds. + decltype(auto) value(index_type idx) const { if (idx < 0 || idx >= size()) BOOST_THROW_EXCEPTION(std::out_of_range("category index out of range")); return vec_meta_.first()[idx]; } - decltype(auto) operator[](int idx) const noexcept { return value(idx); } + /// Return value for index argument. + decltype(auto) operator[](index_type idx) const noexcept { return value(idx); } - /// Returns the number of bins, without extra bins. - int size() const noexcept { return vec_meta_.first().size(); } + /// Returns the number of bins, without over- or underflow. + index_type size() const noexcept { return vec_meta_.first().size(); } /// Returns the options. static constexpr option options() noexcept { return Options; } - /// Returns the metadata. + /// Returns reference to metadata. metadata_type& metadata() noexcept { return vec_meta_.second(); } - /// Returns the metadata (const version). + /// Returns reference to const metadata. const metadata_type& metadata() const noexcept { return vec_meta_.second(); } + bool operator==(const category& o) const noexcept { const auto& a = vec_meta_.first(); const auto& b = o.vec_meta_.first(); diff --git a/include/boost/histogram/axis/integer.hpp b/include/boost/histogram/axis/integer.hpp index ba3227fd..1b14910b 100644 --- a/include/boost/histogram/axis/integer.hpp +++ b/include/boost/histogram/axis/integer.hpp @@ -100,12 +100,12 @@ public: BOOST_THROW_EXCEPTION(std::invalid_argument("cannot shrink circular axis")); } - /// Returns the bin index for the passed argument. + /// Return index for value argument. index_type operator()(value_type x) const noexcept { return index_impl(std::is_floating_point(), x); } - /// Returns axis value for index. + /// Return value for index argument. value_type value(local_index_type i) const noexcept { if (!test(Options, option::circular)) { if (i < 0) return detail::lowest(); @@ -114,19 +114,20 @@ public: return min_ + i; } + /// Return bin for index argument. decltype(auto) operator[](local_index_type idx) const noexcept { return detail::static_if>( [this](auto idx) { return interval_view(*this, idx); }, [this](auto idx) { return this->value(idx); }, idx); } - /// Returns the number of bins, without extra bins. - int size() const noexcept { return size_meta_.first(); } + /// Returns the number of bins, without over- or underflow. + index_type size() const noexcept { return size_meta_.first(); } /// Returns the options. static constexpr option options() noexcept { return Options; } - /// Returns the metadata. + /// Returns reference to metadata. metadata_type& metadata() noexcept { return size_meta_.second(); } - /// Returns the metadata (const version). + /// Returns reference to const metadata. const metadata_type& metadata() const noexcept { return size_meta_.second(); } bool operator==(const integer& o) const noexcept { diff --git a/include/boost/histogram/axis/interval_view.hpp b/include/boost/histogram/axis/interval_view.hpp index 1d259522..c8947331 100644 --- a/include/boost/histogram/axis/interval_view.hpp +++ b/include/boost/histogram/axis/interval_view.hpp @@ -18,9 +18,13 @@ public: // avoid viewing a temporary that goes out of scope interval_view(Axis&& axis, int idx) = delete; + /// Return lower edge of bin. decltype(auto) lower() const noexcept { return axis_.value(idx_); } + /// Return upper edge of bin. decltype(auto) upper() const noexcept { return axis_.value(idx_ + 1); } + /// Return center of bin. decltype(auto) center() const noexcept { return axis_.value(idx_ + 0.5); } + /// Return width of bin. decltype(auto) width() const noexcept { return upper() - lower(); } template diff --git a/include/boost/histogram/axis/polymorphic_bin.hpp b/include/boost/histogram/axis/polymorphic_bin.hpp index 203d2602..1b70938e 100644 --- a/include/boost/histogram/axis/polymorphic_bin.hpp +++ b/include/boost/histogram/axis/polymorphic_bin.hpp @@ -38,11 +38,16 @@ 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 @@ -55,6 +60,7 @@ public: return !operator==(rhs); } + /// Return true if bin is discrete. bool is_discrete() const noexcept { return lower_or_value_ == upper_; } private: diff --git a/include/boost/histogram/axis/regular.hpp b/include/boost/histogram/axis/regular.hpp index eaeb737b..ec77a493 100644 --- a/include/boost/histogram/axis/regular.hpp +++ b/include/boost/histogram/axis/regular.hpp @@ -241,10 +241,10 @@ public: BOOST_THROW_EXCEPTION(std::invalid_argument("cannot shrink circular axis")); } - /// Returns instance of the transform type + /// Return instance of the transform type. const transform_type& transform() const noexcept { return *this; } - /// Returns the bin index for the passed argument. + /// Return index for value argument. index_type operator()(value_type x) const noexcept { // Runs in hot loop, please measure impact of changes auto z = (this->forward(x / unit_type()) - min_) / delta_; @@ -264,7 +264,7 @@ public: return size(); // also returned if x is NaN } - /// Returns axis value for fractional index. + /// Return value for fractional index argument. value_type value(real_index_type i) const noexcept { auto z = i / size(); if (!test(Options, option::circular) && z < 0.0) @@ -277,18 +277,18 @@ public: return this->inverse(z) * unit_type(); } - /// Access bin at index + /// Return bin for index argument. decltype(auto) operator[](index_type idx) const noexcept { return interval_view(*this, idx); } - /// Returns the number of bins, without extra bins. + /// Returns the number of bins, without over- or underflow. index_type size() const noexcept { return size_meta_.first(); } /// Returns the options. static constexpr option options() noexcept { return Options; } - /// Returns the metadata. + /// Returns reference to metadata. metadata_type& metadata() noexcept { return size_meta_.second(); } - /// Returns the metadata (const version). + /// Returns reference to const metadata. const metadata_type& metadata() const noexcept { return size_meta_.second(); } bool operator==(const regular& o) const noexcept { @@ -296,7 +296,6 @@ public: detail::relaxed_equal(metadata(), o.metadata()) && min_ == o.min_ && delta_ == o.delta_; } - bool operator!=(const regular& o) const noexcept { return !operator==(o); } template diff --git a/include/boost/histogram/axis/variable.hpp b/include/boost/histogram/axis/variable.hpp index cb37cd02..bf054daf 100644 --- a/include/boost/histogram/axis/variable.hpp +++ b/include/boost/histogram/axis/variable.hpp @@ -121,7 +121,7 @@ public: /** Construct variable axis from initializer list of bin edges. * - * @param list std::initializer_list of bin edges. + * @param list `std::initializer_list` of bin edges. * @param meta description of the axis. * @param alloc allocator instance to use. */ @@ -142,8 +142,8 @@ public: for (index_type i = begin; i <= end; i += merge) vec.emplace_back(*(beg + i)); } - /// Returns the bin index for the passed argument. - int operator()(value_type x) const noexcept { + /// Return index for value argument. + index_type operator()(value_type x) const noexcept { const auto& v = vec_meta_.first(); if (test(Options, option::circular)) { const auto a = v[0]; @@ -153,7 +153,7 @@ public: return std::upper_bound(v.begin(), v.end(), x) - v.begin() - 1; } - /// Returns axis value for fractional index. + /// Return value for fractional index argument. value_type value(real_index_type i) const noexcept { const auto& v = vec_meta_.first(); if (test(Options, option::circular)) { @@ -173,18 +173,20 @@ public: return (1.0 - z) * v[k] + z * v[k + 1]; } + /// Return bin for index argument. auto operator[](index_type idx) const noexcept { return interval_view(*this, idx); } - /// Returns the number of bins, without extra bins. + /// Returns the number of bins, without over- or underflow. index_type size() const noexcept { return vec_meta_.first().size() - 1; } /// Returns the options. static constexpr option options() noexcept { return Options; } - /// Returns the metadata. + /// Returns reference to metadata. metadata_type& metadata() noexcept { return vec_meta_.second(); } - /// Returns the metadata (const version). + /// Returns reference to const metadata. const metadata_type& metadata() const noexcept { return vec_meta_.second(); } + bool operator==(const variable& o) const noexcept { const auto& a = vec_meta_.first(); const auto& b = o.vec_meta_.first(); @@ -193,6 +195,7 @@ public: } bool operator!=(const variable<>& o) const noexcept { return !operator==(o); } + /// Return allocator instance. allocator_type get_allocator() const { return vec_meta_.first().get_allocator(); } template diff --git a/include/boost/histogram/axis/variant.hpp b/include/boost/histogram/axis/variant.hpp index d4fbd55a..cc94567c 100644 --- a/include/boost/histogram/axis/variant.hpp +++ b/include/boost/histogram/axis/variant.hpp @@ -108,14 +108,17 @@ public: return *this; } - int size() const { + /// Return size of axis. + index_type size() const { return visit([](const auto& x) { return x.size(); }, *this); } + /// Return options of axis or option::none if axis has no options. option options() const { return visit([](const auto& x) { return axis::traits::options(x); }, *this); } + /// Return reference to const metadata or instance of null_type if axis has no metadata. const metadata_type& metadata() const { return visit( [](const auto& a) -> const metadata_type& { @@ -136,6 +139,7 @@ public: *this); } + /// Return reference to metadata or instance of null_type if axis has no metadata. metadata_type& metadata() { return visit( [](auto& a) -> metadata_type& { @@ -156,26 +160,25 @@ public: *this); } - // Throws invalid_argument exception if axis has incompatible call signature + /// Return index for value argument. + /// Throws std::invalid_argument if axis has incompatible call signature. template - int operator()(const U& u) const { + index_type operator()(const U& u) const { return visit([&u](const auto& a) { return traits::index(a, u); }, *this); } - // // Throws invalid_argument exception if axis has incompatible call signature - // template - // std::pair update(const U& u) { - // return visit([&u](auto& a) { return traits::update(a, u); }, *this); - // } - - // Only works for axes with value method that returns something convertible to - // double and will throw a runtime_error otherwise, see axis::traits::value - double value(double idx) const { + /// Return value for index argument. + /// Only works for axes with value method that returns something convertible to + /// double and will throw a runtime_error otherwise, see axis::traits::value(). + double value(real_index_type idx) const { return visit([idx](const auto& a) { return traits::value_as(a, idx); }, *this); } - auto operator[](const int idx) const { + /// Return bin for index argument. + /// Only works for axes with value method that returns something convertible to + /// double and will throw a runtime_error otherwise, see axis::traits::value(). + auto operator[](index_type idx) const { return visit( [idx](const auto& a) { return detail::value_method_switch_with_return_type* v); }; -/// Apply visitor to variant +/// Apply visitor to variant. template auto visit(Visitor&& vis, Variant&& var) -> detail::visitor_return_type { @@ -242,35 +245,35 @@ auto visit(Visitor&& vis, Variant&& var) static_cast(var)); } -/// Return lvalue reference to T, throws unspecified exception if type does not match +/// Return lvalue reference to T, throws unspecified exception if type does not match. template T& get(variant& v) { using B = typename variant::base_type; return boost::get(static_cast(v)); } -/// Return rvalue reference to T, throws unspecified exception if type does not match +/// Return rvalue reference to T, throws unspecified exception if type does not match. template T&& get(variant&& v) { using B = typename variant::base_type; return boost::get(static_cast(v)); } -/// Return const reference to T, throws unspecified exception if type does not match +/// Return const reference to T, throws unspecified exception if type does not match. template const T& get(const variant& v) { using B = typename variant::base_type; return boost::get(static_cast(v)); } -/// Returns pointer to T in variant or null pointer if type does not match +/// Returns pointer to T in variant or null pointer if type does not match. template T* get_if(variant* v) { using B = typename variant::base_type; return boost::relaxed_get(static_cast(v)); } -/// Returns pointer to const T in variant or null pointer if type does not match +/// Returns pointer to const T in variant or null pointer if type does not match. template const T* get_if(const variant* v) { using B = typename variant::base_type; @@ -278,19 +281,17 @@ const T* get_if(const variant* v) { } #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED -// pass-through version for generic programming, if U is axis instead of variant +// pass-through versions of get and get_if for generic programming template decltype(auto) get(U&& u) { return static_cast>(u); } -// pass-through version for generic programming, if U is axis instead of variant template T* get_if(U* u) { return std::is_same>::value ? reinterpret_cast(u) : nullptr; } -// pass-through version for generic programming, if U is axis instead of variant template const T* get_if(const U* u) { return std::is_same>::value ? reinterpret_cast(u) diff --git a/include/boost/histogram/histogram.hpp b/include/boost/histogram/histogram.hpp index 07203346..7c64db74 100644 --- a/include/boost/histogram/histogram.hpp +++ b/include/boost/histogram/histogram.hpp @@ -118,23 +118,26 @@ public: return detail::for_each_axis(axes_, std::forward(unary)); } - /** Fill histogram with values and optional weight or sample. + /** Fill histogram with values, an optional weight, and/or a sample. Arguments are passed in order to the axis objects. Passing an argument type that is not convertible to the value type accepted by the axis or passing the wrong number - of arguments causes a throw of std::invalid_argument. + of arguments causes a throw of `std::invalid_argument`. - **Axis with multiple arguments** - If the histogram contains an axis which accepts a std::tuple of arguments, the - arguments for that axis need to passed as a std::tuple, for example, - std::make_tuple(1.2, 2.3). If the histogram contains only this axis and no other, + __Axis with multiple arguments__ + + If the histogram contains an axis which accepts a `std::tuple` of arguments, the + arguments for that axis need to passed as a `std::tuple`, for example, + `std::make_tuple(1.2, 2.3)`. If the histogram contains only this axis and no other, the arguments can be passed directly. - **Weights** + __Optional weight__ + An optional weight can be passed as the first or last argument with the weight helper function. Compilation fails if the storage elements do not support weights. - **Samples** + __Samples__ + If the storage elements accept samples, pass them with the sample helper function in addition to the axis arguments, which can be the first or last argument. The sample helper function can pass one or more arguments to the storage element. If @@ -146,7 +149,7 @@ public: return operator()(std::forward_as_tuple(ts...)); } - /// Fill histogram with values and optional weight or sample from a tuple. + /// Fill histogram with values, an optional weight, and/or a sample from a `std::tuple`. template auto operator()(const std::tuple& t) { return detail::fill(storage_, axes_, t); @@ -189,7 +192,7 @@ public: return at(std::forward_as_tuple(t, ts...)); } - /// Access cell value at integral indices stored in std::tuple. + /// Access cell value at integral indices stored in `std::tuple`. /// @copydoc at(int t, Ts... ts) template decltype(auto) at(const std::tuple& t) { @@ -198,7 +201,7 @@ public: return storage_[*idx]; } - /// Access cell value at integral indices stored in std::tuple (read-only). + /// Access cell value at integral indices stored in `std::tuple` (read-only). /// @copydoc at(int t, Ts... ts) template decltype(auto) at(const std::tuple& t) const { @@ -225,13 +228,13 @@ public: return storage_[*idx]; } - /// Access value at index (number for rank = 1, else std::tuple or iterable). + /// Access value at index (number for rank = 1, else `std::tuple` or iterable). template decltype(auto) operator[](const T& t) { return at(t); } - /// Access value at index (number for rank = 1, else std::tuple or iterable; read-only). + /// @copydoc operator[] template decltype(auto) operator[](const T& t) const { return at(t);