mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-09 23:04:07 +00:00
improve docstrings for axes, explain move issue (#382)
This commit is contained in:
parent
652c7f8ebb
commit
04946089f4
@ -51,7 +51,7 @@ An [*Axis] maps input values to indices. It holds state specific to that axis, l
|
||||
* `a` and `b` are values of type `A`
|
||||
* `i` and `j` are indices of type [headerref boost/histogram/fwd.hpp `boost::histogram::axis::index_type`]
|
||||
* `n` is a value of type `unsigned`
|
||||
* `M` is a metadata type that is [@https://en.cppreference.com/w/cpp/named_req/CopyConstructible CopyConstructible] and [@https://en.cppreference.com/w/cpp/named_req/CopyAssignable CopyAssignable] and *nothrow* [@https://en.cppreference.com/w/cpp/named_req/MoveAssignable MoveAssignable].
|
||||
* `M` is a metadata type that is [@https://en.cppreference.com/w/cpp/named_req/DefaultConstructible DefaultConstructible], [@https://en.cppreference.com/w/cpp/named_req/CopyConstructible CopyConstructible] and [@https://en.cppreference.com/w/cpp/named_req/CopyAssignable CopyAssignable]. It it supports moves, it must be *nothrow* [@https://en.cppreference.com/w/cpp/named_req/MoveAssignable MoveAssignable].
|
||||
* `ar` is a value of an archive with Boost.Serialization semantics
|
||||
|
||||
[table Valid expressions
|
||||
|
@ -39,10 +39,14 @@ class boolean : public iterator_mixin<boolean<MetaData>>,
|
||||
|
||||
public:
|
||||
/** Construct a boolean axis.
|
||||
*
|
||||
* @param meta description of the axis.
|
||||
|
||||
@param meta description of the axis.
|
||||
|
||||
The constructor is nothrow if meta is nothrow move constructible.
|
||||
*/
|
||||
explicit boolean(metadata_type meta = {}) : metadata_base(std::move(meta)) {}
|
||||
explicit boolean(metadata_type meta = {}) noexcept(
|
||||
std::is_nothrow_move_constructible<metadata_type>::value)
|
||||
: metadata_base(std::move(meta)) {}
|
||||
|
||||
/// Return index for value argument.
|
||||
index_type index(value_type x) const noexcept { return static_cast<index_type>(x); }
|
||||
|
@ -28,18 +28,18 @@ namespace axis {
|
||||
|
||||
/** Maps at a set of unique values to bin indices.
|
||||
|
||||
The axis maps a set of values to bins, following the order of arguments in the
|
||||
constructor. The optional overflow bin for this axis counts input values that
|
||||
are not part of the set. Binning has O(N) complexity, but with a very small
|
||||
factor. For small N (the typical use case) it beats other kinds of lookup.
|
||||
The axis maps a set of values to bins, following the order of arguments in the
|
||||
constructor. The optional overflow bin for this axis counts input values that
|
||||
are not part of the set. Binning has O(N) complexity, but with a very small
|
||||
factor. For small N (the typical use case) it beats other kinds of lookup.
|
||||
|
||||
@tparam Value input value type, must be equal-comparable.
|
||||
@tparam MetaData type to store meta data.
|
||||
@tparam Options see boost::histogram::axis::option.
|
||||
@tparam Allocator allocator to use for dynamic memory management.
|
||||
@tparam Value input value type, must be equal-comparable.
|
||||
@tparam MetaData type to store meta data.
|
||||
@tparam Options see boost::histogram::axis::option.
|
||||
@tparam Allocator allocator to use for dynamic memory management.
|
||||
|
||||
The options `underflow` and `circular` are not allowed. The options `growth`
|
||||
and `overflow` are mutually exclusive.
|
||||
The options `underflow` and `circular` are not allowed. The options `growth`
|
||||
and `overflow` are mutually exclusive.
|
||||
*/
|
||||
template <class Value, class MetaData, class Options, class Allocator>
|
||||
class category : public iterator_mixin<category<Value, MetaData, Options, Allocator>>,
|
||||
@ -56,13 +56,20 @@ public:
|
||||
constexpr category() = default;
|
||||
explicit category(allocator_type alloc) : vec_(alloc) {}
|
||||
|
||||
/** Construct from iterator range of unique values.
|
||||
/** Construct from forward iterator range of unique values.
|
||||
|
||||
@param begin begin of category range of unique values.
|
||||
@param end end of category range of unique values.
|
||||
@param meta description of the axis (optional).
|
||||
@param options see boost::histogram::axis::option (optional).
|
||||
@param alloc allocator instance to use (optional).
|
||||
@param begin begin of category range of unique values.
|
||||
@param end end of category range of unique values.
|
||||
@param meta description of the axis (optional).
|
||||
@param options see boost::histogram::axis::option (optional).
|
||||
@param alloc allocator instance to use (optional).
|
||||
|
||||
The constructor throws `std::invalid_argument` if iterator range is invalid. If the
|
||||
range contains duplicated values, the behavior of the axis is undefined.
|
||||
|
||||
The arguments meta and alloc are passed by value. If you move either of them into the
|
||||
axis and the constructor throws, their values are lost. Do not move if you cannot
|
||||
guarantee that the bin description is not valid.
|
||||
*/
|
||||
template <class It, class = detail::requires_iterator<It>>
|
||||
category(It begin, It end, metadata_type meta = {}, options_type options = {},
|
||||
|
@ -31,11 +31,13 @@ namespace axis {
|
||||
|
||||
/** Axis for an interval of integer values with unit steps.
|
||||
|
||||
Binning is a O(1) operation. This axis bins faster than a regular axis.
|
||||
Binning is a O(1) operation. This axis bins even faster than a regular axis.
|
||||
|
||||
@tparam Value input value type. Must be integer or floating point.
|
||||
@tparam MetaData type to store meta data.
|
||||
@tparam Options see boost::histogram::axis::option.
|
||||
The options `growth` and `circular` are mutually exclusive.
|
||||
|
||||
@tparam Value input value type. Must be integer or floating point.
|
||||
@tparam MetaData type to store meta data.
|
||||
@tparam Options see boost::histogram::axis::option.
|
||||
*/
|
||||
template <class Value, class MetaData, class Options>
|
||||
class integer : public iterator_mixin<integer<Value, MetaData, Options>>,
|
||||
@ -47,23 +49,6 @@ class integer : public iterator_mixin<integer<Value, MetaData, Options>>,
|
||||
using options_type =
|
||||
detail::replace_default<Options, decltype(option::underflow | option::overflow)>;
|
||||
|
||||
static_assert(std::is_integral<value_type>::value ||
|
||||
std::is_floating_point<value_type>::value,
|
||||
"integer axis requires floating point or integral type");
|
||||
|
||||
static_assert(!options_type::test(option::circular | option::growth) ||
|
||||
(options_type::test(option::circular) ^
|
||||
options_type::test(option::growth)),
|
||||
"circular and growth options are mutually exclusive");
|
||||
|
||||
static_assert(std::is_floating_point<value_type>::value ||
|
||||
(!options_type::test(option::circular) &&
|
||||
!options_type::test(option::growth)) ||
|
||||
(!options_type::test(option::overflow) &&
|
||||
!options_type::test(option::underflow)),
|
||||
"circular or growing integer axis with integral type "
|
||||
"cannot have entries in underflow or overflow bins");
|
||||
|
||||
using local_index_type = std::conditional_t<std::is_integral<value_type>::value,
|
||||
index_type, real_index_type>;
|
||||
|
||||
@ -72,18 +57,37 @@ public:
|
||||
|
||||
/** Construct over semi-open integer interval [start, stop).
|
||||
|
||||
@param start first integer of covered range.
|
||||
@param stop one past last integer of covered range.
|
||||
@param meta description of the axis (optional).
|
||||
@param options see boost::histogram::axis::option (optional).
|
||||
@param start first integer of covered range.
|
||||
@param stop one past last integer of covered range.
|
||||
@param meta description of the axis (optional).
|
||||
@param options see boost::histogram::axis::option (optional).
|
||||
|
||||
The constructor throws `std::invalid_argument` if start is not less than stop.
|
||||
|
||||
The arguments meta and alloc are passed by value. If you move either of them into the
|
||||
axis and the constructor throws, their values are lost. Do not move if you cannot
|
||||
guarantee that the bin description is not valid.
|
||||
*/
|
||||
integer(value_type start, value_type stop, metadata_type meta = {},
|
||||
options_type options = {})
|
||||
: metadata_base(std::move(meta))
|
||||
, size_(static_cast<index_type>(stop - start))
|
||||
, min_(start) {
|
||||
(void)options;
|
||||
if (!(stop >= start))
|
||||
static_assert(
|
||||
std::is_integral<value_type>::value || std::is_floating_point<value_type>::value,
|
||||
"integer axis requires floating point or integral type");
|
||||
|
||||
static_assert(!(options.test(option::circular) && options.test(option::growth)),
|
||||
"circular and growth options are mutually exclusive");
|
||||
|
||||
static_assert(
|
||||
std::is_floating_point<value_type>::value ||
|
||||
!((options.test(option::growth) || options.test(option::circular)) &&
|
||||
(options.test(option::overflow) || options.test(option::underflow))),
|
||||
"circular or growing integer axis with integral type "
|
||||
"cannot have entries in underflow or overflow bins");
|
||||
|
||||
if (!(stop >= start)) // double negation so it works with NaN
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("stop >= start required"));
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,15 @@ class metadata_base {
|
||||
protected:
|
||||
using metadata_type = Metadata;
|
||||
|
||||
static_assert(std::is_default_constructible<metadata_type>::value,
|
||||
"metadata must be default constructible");
|
||||
|
||||
static_assert(std::is_copy_constructible<metadata_type>::value,
|
||||
"metadata must be copy constructible");
|
||||
|
||||
static_assert(std::is_copy_assignable<metadata_type>::value,
|
||||
"metadata must be copy assignable");
|
||||
|
||||
// std::string explicitly guarantees nothrow only in C++17
|
||||
static_assert(std::is_same<metadata_type, std::string>::value ||
|
||||
std::is_nothrow_move_constructible<metadata_type>::value,
|
||||
@ -45,15 +54,15 @@ protected:
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable metadata_type data_;
|
||||
|
||||
public:
|
||||
/// Returns reference to metadata.
|
||||
metadata_type& metadata() noexcept { return data_; }
|
||||
|
||||
/// Returns reference to mutable metadata from const axis.
|
||||
metadata_type& metadata() const noexcept { return data_; }
|
||||
|
||||
private:
|
||||
mutable metadata_type data_;
|
||||
};
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
@ -167,20 +167,20 @@ step_type<T> step(T t) {
|
||||
|
||||
/** Axis for equidistant intervals on the real line.
|
||||
|
||||
The most common binning strategy. Very fast. Binning is a O(1) operation.
|
||||
The most common binning strategy. Very fast. Binning is a O(1) operation.
|
||||
|
||||
If the axis has an overflow bin (the default), a value on the upper edge of the last
|
||||
bin is put in the overflow bin. The axis range represents a semi-open interval.
|
||||
If the axis has an overflow bin (the default), a value on the upper edge of the last
|
||||
bin is put in the overflow bin. The axis range represents a semi-open interval.
|
||||
|
||||
If the overflow bin is deactivated, then a value on the upper edge of the last bin is
|
||||
still counted towards the last bin. The axis range represents a closed interval. This
|
||||
is the desired behavior for random numbers drawn from a bounded interval, which is
|
||||
usually closed.
|
||||
If the overflow bin is deactivated, then a value on the upper edge of the last bin is
|
||||
still counted towards the last bin. The axis range represents a closed interval.
|
||||
|
||||
@tparam Value input value type, must be floating point.
|
||||
@tparam Transform builtin or user-defined transform type.
|
||||
@tparam MetaData type to store meta data.
|
||||
@tparam Options see boost::histogram::axis::option.
|
||||
The options `growth` and `circular` are mutually exclusive.
|
||||
|
||||
@tparam Value input value type, must be floating point.
|
||||
@tparam Transform builtin or user-defined transform type.
|
||||
@tparam MetaData type to store meta data.
|
||||
@tparam Options see boost::histogram::axis::option.
|
||||
*/
|
||||
template <class Value, class Transform, class MetaData, class Options>
|
||||
class regular : public iterator_mixin<regular<Value, Transform, MetaData, Options>>,
|
||||
@ -202,12 +202,19 @@ public:
|
||||
|
||||
/** Construct n bins over real transformed range [start, stop).
|
||||
|
||||
@param trans transform instance to use.
|
||||
@param n number of bins.
|
||||
@param start low edge of first bin.
|
||||
@param stop high edge of last bin.
|
||||
@param meta description of the axis (optional).
|
||||
@param options see boost::histogram::axis::option (optional).
|
||||
@param trans transform instance to use.
|
||||
@param n number of bins.
|
||||
@param start low edge of first bin.
|
||||
@param stop high edge of last bin.
|
||||
@param meta description of the axis (optional).
|
||||
@param options see boost::histogram::axis::option (optional).
|
||||
|
||||
The constructor throws `std::invalid_argument` if n is zero, or if start and stop
|
||||
produce an invalid range after transformation.
|
||||
|
||||
The arguments meta and alloc are passed by value. If you move either of them into the
|
||||
axis and the constructor throws, their values are lost. Do not move if you cannot
|
||||
guarantee that the bin description is not valid.
|
||||
*/
|
||||
regular(transform_type trans, unsigned n, value_type start, value_type stop,
|
||||
metadata_type meta = {}, options_type options = {})
|
||||
@ -223,10 +230,9 @@ public:
|
||||
"transform must be no-throw move assignable");
|
||||
static_assert(std::is_floating_point<internal_value_type>::value,
|
||||
"regular axis requires floating point type");
|
||||
static_assert((!options.test(option::circular) && !options.test(option::growth)) ||
|
||||
(options.test(option::circular) ^ options.test(option::growth)),
|
||||
static_assert(!(options.test(option::circular) && options.test(option::growth)),
|
||||
"circular and growth options are mutually exclusive");
|
||||
if (size() == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
|
||||
if (size() <= 0) BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
|
||||
if (!std::isfinite(min_) || !std::isfinite(delta_))
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("forward transform of start or stop invalid"));
|
||||
|
@ -68,13 +68,20 @@ public:
|
||||
constexpr variable() = default;
|
||||
explicit variable(allocator_type alloc) : vec_(alloc) {}
|
||||
|
||||
/** Construct from iterator range of bin edges.
|
||||
/** Construct from forward iterator range of bin edges.
|
||||
|
||||
@param begin begin of edge sequence.
|
||||
@param end end of edge sequence.
|
||||
@param meta description of the axis (optional).
|
||||
@param options see boost::histogram::axis::option (optional).
|
||||
@param alloc allocator instance to use (optional).
|
||||
@param begin begin of edge sequence.
|
||||
@param end end of edge sequence.
|
||||
@param meta description of the axis (optional).
|
||||
@param options see boost::histogram::axis::option (optional).
|
||||
@param alloc allocator instance to use (optional).
|
||||
|
||||
The constructor throws `std::invalid_argument` if iterator range is invalid, if less
|
||||
than two edges are provided or if bin edges are not in ascending order.
|
||||
|
||||
The arguments meta and alloc are passed by value. If you move either of them into the
|
||||
axis and the constructor throws, their values are lost. Do not move if you cannot
|
||||
guarantee that the bin description is not valid.
|
||||
*/
|
||||
template <class It, class = detail::requires_iterator<It>>
|
||||
variable(It begin, It end, metadata_type meta = {}, options_type options = {},
|
||||
@ -89,16 +96,21 @@ public:
|
||||
(options.test(option::circular) ^ options.test(option::growth)),
|
||||
"circular and growth options are mutually exclusive");
|
||||
|
||||
if (std::distance(begin, end) < 2)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
|
||||
const auto n = std::distance(begin, end);
|
||||
if (n < 0)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("end must be reachable by incrementing begin"));
|
||||
|
||||
vec_.reserve(std::distance(begin, end));
|
||||
if (n < 2) BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 1 required"));
|
||||
|
||||
vec_.reserve(n);
|
||||
vec_.emplace_back(*begin++);
|
||||
bool strictly_ascending = true;
|
||||
for (; begin != end; ++begin) {
|
||||
strictly_ascending &= vec_.back() < *begin;
|
||||
vec_.emplace_back(*begin);
|
||||
}
|
||||
|
||||
if (!strictly_ascending)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("input sequence must be strictly ascending"));
|
||||
|
Loading…
x
Reference in New Issue
Block a user