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`
|
* `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`]
|
* `i` and `j` are indices of type [headerref boost/histogram/fwd.hpp `boost::histogram::axis::index_type`]
|
||||||
* `n` is a value of type `unsigned`
|
* `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
|
* `ar` is a value of an archive with Boost.Serialization semantics
|
||||||
|
|
||||||
[table Valid expressions
|
[table Valid expressions
|
||||||
|
@ -39,10 +39,14 @@ class boolean : public iterator_mixin<boolean<MetaData>>,
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/** Construct a boolean axis.
|
/** 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.
|
/// Return index for value argument.
|
||||||
index_type index(value_type x) const noexcept { return static_cast<index_type>(x); }
|
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.
|
/** 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
|
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
|
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
|
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.
|
factor. For small N (the typical use case) it beats other kinds of lookup.
|
||||||
|
|
||||||
@tparam Value input value type, must be equal-comparable.
|
@tparam Value input value type, must be equal-comparable.
|
||||||
@tparam MetaData type to store meta data.
|
@tparam MetaData type to store meta data.
|
||||||
@tparam Options see boost::histogram::axis::option.
|
@tparam Options see boost::histogram::axis::option.
|
||||||
@tparam Allocator allocator to use for dynamic memory management.
|
@tparam Allocator allocator to use for dynamic memory management.
|
||||||
|
|
||||||
The options `underflow` and `circular` are not allowed. The options `growth`
|
The options `underflow` and `circular` are not allowed. The options `growth`
|
||||||
and `overflow` are mutually exclusive.
|
and `overflow` are mutually exclusive.
|
||||||
*/
|
*/
|
||||||
template <class Value, class MetaData, class Options, class Allocator>
|
template <class Value, class MetaData, class Options, class Allocator>
|
||||||
class category : public iterator_mixin<category<Value, MetaData, Options, Allocator>>,
|
class category : public iterator_mixin<category<Value, MetaData, Options, Allocator>>,
|
||||||
@ -56,13 +56,20 @@ public:
|
|||||||
constexpr category() = default;
|
constexpr category() = default;
|
||||||
explicit category(allocator_type alloc) : vec_(alloc) {}
|
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 begin begin of category range of unique values.
|
||||||
@param end end of category range of unique values.
|
@param end end of category range of unique values.
|
||||||
@param meta description of the axis (optional).
|
@param meta description of the axis (optional).
|
||||||
@param options see boost::histogram::axis::option (optional).
|
@param options see boost::histogram::axis::option (optional).
|
||||||
@param alloc allocator instance to use (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>>
|
template <class It, class = detail::requires_iterator<It>>
|
||||||
category(It begin, It end, metadata_type meta = {}, options_type options = {},
|
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.
|
/** 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.
|
The options `growth` and `circular` are mutually exclusive.
|
||||||
@tparam MetaData type to store meta data.
|
|
||||||
@tparam Options see boost::histogram::axis::option.
|
@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>
|
template <class Value, class MetaData, class Options>
|
||||||
class integer : public iterator_mixin<integer<Value, MetaData, 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 =
|
using options_type =
|
||||||
detail::replace_default<Options, decltype(option::underflow | option::overflow)>;
|
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,
|
using local_index_type = std::conditional_t<std::is_integral<value_type>::value,
|
||||||
index_type, real_index_type>;
|
index_type, real_index_type>;
|
||||||
|
|
||||||
@ -72,18 +57,37 @@ public:
|
|||||||
|
|
||||||
/** Construct over semi-open integer interval [start, stop).
|
/** Construct over semi-open integer interval [start, stop).
|
||||||
|
|
||||||
@param start first integer of covered range.
|
@param start first integer of covered range.
|
||||||
@param stop one past last integer of covered range.
|
@param stop one past last integer of covered range.
|
||||||
@param meta description of the axis (optional).
|
@param meta description of the axis (optional).
|
||||||
@param options see boost::histogram::axis::option (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 = {},
|
integer(value_type start, value_type stop, metadata_type meta = {},
|
||||||
options_type options = {})
|
options_type options = {})
|
||||||
: metadata_base(std::move(meta))
|
: metadata_base(std::move(meta))
|
||||||
, size_(static_cast<index_type>(stop - start))
|
, size_(static_cast<index_type>(stop - start))
|
||||||
, min_(start) {
|
, min_(start) {
|
||||||
(void)options;
|
static_assert(
|
||||||
if (!(stop >= start))
|
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"));
|
BOOST_THROW_EXCEPTION(std::invalid_argument("stop >= start required"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,15 @@ class metadata_base {
|
|||||||
protected:
|
protected:
|
||||||
using metadata_type = Metadata;
|
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
|
// std::string explicitly guarantees nothrow only in C++17
|
||||||
static_assert(std::is_same<metadata_type, std::string>::value ||
|
static_assert(std::is_same<metadata_type, std::string>::value ||
|
||||||
std::is_nothrow_move_constructible<metadata_type>::value,
|
std::is_nothrow_move_constructible<metadata_type>::value,
|
||||||
@ -45,15 +54,15 @@ protected:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
mutable metadata_type data_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Returns reference to metadata.
|
/// Returns reference to metadata.
|
||||||
metadata_type& metadata() noexcept { return data_; }
|
metadata_type& metadata() noexcept { return data_; }
|
||||||
|
|
||||||
/// Returns reference to mutable metadata from const axis.
|
/// Returns reference to mutable metadata from const axis.
|
||||||
metadata_type& metadata() const noexcept { return data_; }
|
metadata_type& metadata() const noexcept { return data_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable metadata_type data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||||
|
@ -167,20 +167,20 @@ step_type<T> step(T t) {
|
|||||||
|
|
||||||
/** Axis for equidistant intervals on the real line.
|
/** 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
|
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.
|
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
|
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
|
still counted towards the last bin. The axis range represents a closed interval.
|
||||||
is the desired behavior for random numbers drawn from a bounded interval, which is
|
|
||||||
usually closed.
|
|
||||||
|
|
||||||
@tparam Value input value type, must be floating point.
|
The options `growth` and `circular` are mutually exclusive.
|
||||||
@tparam Transform builtin or user-defined transform type.
|
|
||||||
@tparam MetaData type to store meta data.
|
@tparam Value input value type, must be floating point.
|
||||||
@tparam Options see boost::histogram::axis::option.
|
@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>
|
template <class Value, class Transform, class MetaData, class Options>
|
||||||
class regular : public iterator_mixin<regular<Value, Transform, MetaData, 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).
|
/** Construct n bins over real transformed range [start, stop).
|
||||||
|
|
||||||
@param trans transform instance to use.
|
@param trans transform instance to use.
|
||||||
@param n number of bins.
|
@param n number of bins.
|
||||||
@param start low edge of first bin.
|
@param start low edge of first bin.
|
||||||
@param stop high edge of last bin.
|
@param stop high edge of last bin.
|
||||||
@param meta description of the axis (optional).
|
@param meta description of the axis (optional).
|
||||||
@param options see boost::histogram::axis::option (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,
|
regular(transform_type trans, unsigned n, value_type start, value_type stop,
|
||||||
metadata_type meta = {}, options_type options = {})
|
metadata_type meta = {}, options_type options = {})
|
||||||
@ -223,10 +230,9 @@ public:
|
|||||||
"transform must be no-throw move assignable");
|
"transform must be no-throw move assignable");
|
||||||
static_assert(std::is_floating_point<internal_value_type>::value,
|
static_assert(std::is_floating_point<internal_value_type>::value,
|
||||||
"regular axis requires floating point type");
|
"regular axis requires floating point type");
|
||||||
static_assert((!options.test(option::circular) && !options.test(option::growth)) ||
|
static_assert(!(options.test(option::circular) && options.test(option::growth)),
|
||||||
(options.test(option::circular) ^ options.test(option::growth)),
|
|
||||||
"circular and growth options are mutually exclusive");
|
"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_))
|
if (!std::isfinite(min_) || !std::isfinite(delta_))
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
std::invalid_argument("forward transform of start or stop invalid"));
|
std::invalid_argument("forward transform of start or stop invalid"));
|
||||||
|
@ -68,13 +68,20 @@ public:
|
|||||||
constexpr variable() = default;
|
constexpr variable() = default;
|
||||||
explicit variable(allocator_type alloc) : vec_(alloc) {}
|
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 begin begin of edge sequence.
|
||||||
@param end end of edge sequence.
|
@param end end of edge sequence.
|
||||||
@param meta description of the axis (optional).
|
@param meta description of the axis (optional).
|
||||||
@param options see boost::histogram::axis::option (optional).
|
@param options see boost::histogram::axis::option (optional).
|
||||||
@param alloc allocator instance to use (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>>
|
template <class It, class = detail::requires_iterator<It>>
|
||||||
variable(It begin, It end, metadata_type meta = {}, options_type options = {},
|
variable(It begin, It end, metadata_type meta = {}, options_type options = {},
|
||||||
@ -89,16 +96,21 @@ public:
|
|||||||
(options.test(option::circular) ^ options.test(option::growth)),
|
(options.test(option::circular) ^ options.test(option::growth)),
|
||||||
"circular and growth options are mutually exclusive");
|
"circular and growth options are mutually exclusive");
|
||||||
|
|
||||||
if (std::distance(begin, end) < 2)
|
const auto n = std::distance(begin, end);
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
|
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++);
|
vec_.emplace_back(*begin++);
|
||||||
bool strictly_ascending = true;
|
bool strictly_ascending = true;
|
||||||
for (; begin != end; ++begin) {
|
for (; begin != end; ++begin) {
|
||||||
strictly_ascending &= vec_.back() < *begin;
|
strictly_ascending &= vec_.back() < *begin;
|
||||||
vec_.emplace_back(*begin);
|
vec_.emplace_back(*begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strictly_ascending)
|
if (!strictly_ascending)
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
std::invalid_argument("input sequence must be strictly ascending"));
|
std::invalid_argument("input sequence must be strictly ascending"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user