mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-11 13:14:06 +00:00
better reference docu
This commit is contained in:
parent
1bd67c780e
commit
fd0b7dea8d
@ -31,36 +31,41 @@ template <typename RealType>
|
||||
class sum {
|
||||
public:
|
||||
sum() = default;
|
||||
explicit sum(const RealType& value) noexcept : sum_(value), cor_(0) {}
|
||||
|
||||
/// Initialize sum to value
|
||||
explicit sum(const RealType& value) noexcept : large_(value) {}
|
||||
|
||||
/// Set sum to value
|
||||
sum& operator=(const RealType& value) noexcept {
|
||||
sum_ = value;
|
||||
cor_ = 0;
|
||||
large_ = value;
|
||||
small_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void operator()() { operator+=(1); }
|
||||
/// Increment sum by one
|
||||
sum& operator++() { return operator+=(1); }
|
||||
|
||||
void operator()(const RealType& x) { operator+=(x); }
|
||||
|
||||
sum& operator+=(const RealType& x) {
|
||||
auto temp = sum_ + x; // prevent optimization
|
||||
if (std::abs(sum_) >= std::abs(x))
|
||||
cor_ += (sum_ - temp) + x;
|
||||
/// Increment sum by value
|
||||
sum& operator+=(const RealType& value) {
|
||||
auto temp = large_ + value; // prevent optimization
|
||||
if (std::abs(large_) >= std::abs(value))
|
||||
small_ += (large_ - temp) + value;
|
||||
else
|
||||
cor_ += (x - temp) + sum_;
|
||||
sum_ = temp;
|
||||
small_ += (value - temp) + large_;
|
||||
large_ = temp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
sum& operator*=(const RealType& x) {
|
||||
sum_ *= x;
|
||||
cor_ *= x;
|
||||
/// Scale by value
|
||||
sum& operator*=(const RealType& value) {
|
||||
large_ *= value;
|
||||
small_ *= value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator==(const sum<T>& rhs) const noexcept {
|
||||
return sum_ == rhs.sum_ && cor_ == rhs.cor_;
|
||||
return large_ == rhs.large_ && small_ == rhs.small_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -68,17 +73,21 @@ public:
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
const RealType& large() const noexcept { return sum_; }
|
||||
const RealType& small() const noexcept { return cor_; }
|
||||
/// Return large part of the sum.
|
||||
const RealType& large() const { return large_; }
|
||||
|
||||
/// Return small part of the sum.
|
||||
const RealType& small() const { return small_; }
|
||||
|
||||
// allow implicit conversion to RealType
|
||||
operator RealType() const { return sum_ + cor_; }
|
||||
operator RealType() const { return large_ + small_; }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */);
|
||||
|
||||
private:
|
||||
RealType sum_ = 0, cor_ = 0;
|
||||
RealType large_ = RealType();
|
||||
RealType small_ = RealType();
|
||||
};
|
||||
|
||||
} // namespace accumulators
|
||||
|
@ -19,49 +19,45 @@ template <typename RealType>
|
||||
class weighted_sum {
|
||||
public:
|
||||
weighted_sum() = default;
|
||||
explicit weighted_sum(const RealType& value) noexcept : sum_(value), sum2_(value) {}
|
||||
explicit weighted_sum(const RealType& value) noexcept
|
||||
: sum_of_weights_(value), sum_of_weights_squared_(value) {}
|
||||
weighted_sum(const RealType& value, const RealType& variance) noexcept
|
||||
: sum_(value), sum2_(variance) {}
|
||||
: sum_of_weights_(value), sum_of_weights_squared_(variance) {}
|
||||
|
||||
void operator()() {
|
||||
sum_ += 1;
|
||||
sum2_ += 1;
|
||||
}
|
||||
/// Increment by one.
|
||||
weighted_sum& operator++() { return operator+=(1); }
|
||||
|
||||
/// Increment by value.
|
||||
template <typename T>
|
||||
void operator()(const T& w) {
|
||||
sum_ += w;
|
||||
sum2_ += w * w;
|
||||
}
|
||||
|
||||
// used when adding non-weighted histogram to weighted histogram
|
||||
template <typename T>
|
||||
weighted_sum& operator+=(const T& x) {
|
||||
sum_ += x;
|
||||
sum2_ += x;
|
||||
weighted_sum& operator+=(const T& value) {
|
||||
sum_of_weights_ += value;
|
||||
sum_of_weights_squared_ += value * value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Added another weighted sum.
|
||||
template <typename T>
|
||||
weighted_sum& operator+=(const weighted_sum<T>& rhs) {
|
||||
sum_ += static_cast<RealType>(rhs.sum_);
|
||||
sum2_ += static_cast<RealType>(rhs.sum2_);
|
||||
sum_of_weights_ += static_cast<RealType>(rhs.sum_of_weights_);
|
||||
sum_of_weights_squared_ += static_cast<RealType>(rhs.sum_of_weights_squared_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Scale by value.
|
||||
weighted_sum& operator*=(const RealType& x) {
|
||||
sum_ *= x;
|
||||
sum2_ *= x * x;
|
||||
sum_of_weights_ *= x;
|
||||
sum_of_weights_squared_ *= x * x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const RealType& rhs) const noexcept {
|
||||
return sum_ == rhs && sum2_ == rhs;
|
||||
return sum_of_weights_ == rhs && sum_of_weights_squared_ == rhs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator==(const weighted_sum<T>& rhs) const noexcept {
|
||||
return sum_ == rhs.sum_ && sum2_ == rhs.sum2_;
|
||||
return sum_of_weights_ == rhs.sum_of_weights_ &&
|
||||
sum_of_weights_squared_ == rhs.sum_of_weights_squared_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -69,20 +65,24 @@ public:
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
const RealType& value() const noexcept { return sum_; }
|
||||
const RealType& variance() const noexcept { return sum2_; }
|
||||
/// Return value of the sum.
|
||||
const RealType& value() const noexcept { return sum_of_weights_; }
|
||||
|
||||
/// Return estimated variance of the sum.
|
||||
const RealType& variance() const noexcept { return sum_of_weights_squared_; }
|
||||
|
||||
// lossy conversion must be explicit
|
||||
template <typename T>
|
||||
template <class T>
|
||||
explicit operator T() const {
|
||||
return static_cast<T>(sum_);
|
||||
return static_cast<T>(sum_of_weights_);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */);
|
||||
|
||||
private:
|
||||
RealType sum_ = RealType(), sum2_ = RealType();
|
||||
RealType sum_of_weights_ = RealType();
|
||||
RealType sum_of_weights_squared_ = RealType();
|
||||
};
|
||||
|
||||
} // namespace accumulators
|
||||
|
@ -46,16 +46,23 @@ public:
|
||||
using const_iterator = iterator<Derived>;
|
||||
using const_reverse_iterator = boost::reverse_iterator<const_iterator>;
|
||||
|
||||
/// Bin iterator to beginning of the axis (read-only).
|
||||
const_iterator begin() const noexcept {
|
||||
return const_iterator(*static_cast<const Derived*>(this), 0);
|
||||
}
|
||||
|
||||
/// Bin iterator to the end of the axis (read-only).
|
||||
const_iterator end() const noexcept {
|
||||
return const_iterator(*static_cast<const Derived*>(this),
|
||||
static_cast<const Derived*>(this)->size());
|
||||
}
|
||||
|
||||
/// Reverse bin iterator to the last entry of the axis (read-only).
|
||||
const_reverse_iterator rbegin() const noexcept {
|
||||
return boost::make_reverse_iterator(end());
|
||||
}
|
||||
|
||||
/// Reverse bin iterator to the end (read-only).
|
||||
const_reverse_iterator rend() const noexcept {
|
||||
return boost::make_reverse_iterator(begin());
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ struct sqrt {
|
||||
|
||||
/// Pow transform for equidistant bins in pow-space.
|
||||
struct pow {
|
||||
double power = 1;
|
||||
double power = 1; /**< power index */
|
||||
|
||||
explicit pow(double p) : power(p) {}
|
||||
pow() = default;
|
||||
|
@ -162,11 +162,11 @@ public:
|
||||
return visit([&u](const auto& a) { return traits::index(a, u); }, *this);
|
||||
}
|
||||
|
||||
// Throws invalid_argument exception if axis has incompatible call signature
|
||||
template <class U>
|
||||
std::pair<int, int> update(const U& u) {
|
||||
return visit([&u](auto& a) { return traits::update(a, u); }, *this);
|
||||
}
|
||||
// // Throws invalid_argument exception if axis has incompatible call signature
|
||||
// template <class U>
|
||||
// std::pair<int, int> 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
|
||||
@ -212,9 +212,9 @@ public:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned);
|
||||
|
||||
template <class Functor, class Variant>
|
||||
friend auto visit(Functor&&, Variant &&)
|
||||
-> detail::visitor_return_type<Functor, Variant>;
|
||||
template <class Visitor, class Variant>
|
||||
friend auto visit(Visitor&&, Variant &&)
|
||||
-> detail::visitor_return_type<Visitor, Variant>;
|
||||
|
||||
template <class T, class... Us>
|
||||
friend T& get(variant<Us...>& v);
|
||||
@ -232,43 +232,52 @@ public:
|
||||
friend const T* get_if(const variant<Us...>* v);
|
||||
};
|
||||
|
||||
template <class Functor, class Variant>
|
||||
auto visit(Functor&& f, Variant&& v) -> detail::visitor_return_type<Functor, Variant> {
|
||||
using R = detail::visitor_return_type<Functor, Variant>;
|
||||
/// Apply visitor to variant
|
||||
template <class Visitor, class Variant>
|
||||
auto visit(Visitor&& vis, Variant&& var)
|
||||
-> detail::visitor_return_type<Visitor, Variant> {
|
||||
using R = detail::visitor_return_type<Visitor, Variant>;
|
||||
using B = detail::copy_qualifiers<Variant, typename detail::naked<Variant>::base_type>;
|
||||
return boost::apply_visitor(detail::functor_wrapper<Functor, R>(f), static_cast<B>(v));
|
||||
return boost::apply_visitor(detail::functor_wrapper<Visitor, R>(vis),
|
||||
static_cast<B>(var));
|
||||
}
|
||||
|
||||
/// Return lvalue reference to T, throws unspecified exception if type does not match
|
||||
template <class T, class... Us>
|
||||
T& get(variant<Us...>& v) {
|
||||
using B = typename variant<Us...>::base_type;
|
||||
return boost::get<T>(static_cast<B&>(v));
|
||||
}
|
||||
|
||||
/// Return rvalue reference to T, throws unspecified exception if type does not match
|
||||
template <class T, class... Us>
|
||||
T&& get(variant<Us...>&& v) {
|
||||
using B = typename variant<Us...>::base_type;
|
||||
return boost::get<T>(static_cast<B&&>(v));
|
||||
}
|
||||
|
||||
/// Return const reference to T, throws unspecified exception if type does not match
|
||||
template <class T, class... Us>
|
||||
const T& get(const variant<Us...>& v) {
|
||||
using B = typename variant<Us...>::base_type;
|
||||
return boost::get<T>(static_cast<const B&>(v));
|
||||
}
|
||||
|
||||
/// Returns pointer to T in variant or null pointer if type does not match
|
||||
template <class T, class... Us>
|
||||
T* get_if(variant<Us...>* v) {
|
||||
using B = typename variant<Us...>::base_type;
|
||||
return boost::relaxed_get<T>(static_cast<B*>(v));
|
||||
}
|
||||
|
||||
/// Returns pointer to const T in variant or null pointer if type does not match
|
||||
template <class T, class... Us>
|
||||
const T* get_if(const variant<Us...>* v) {
|
||||
using B = typename variant<Us...>::base_type;
|
||||
return boost::relaxed_get<T>(static_cast<const B*>(v));
|
||||
}
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
// pass-through version for generic programming, if U is axis instead of variant
|
||||
template <class T, class U>
|
||||
decltype(auto) get(U&& u) {
|
||||
@ -287,6 +296,8 @@ const T* get_if(const U* u) {
|
||||
return std::is_same<T, detail::naked<U>>::value ? reinterpret_cast<const T*>(u)
|
||||
: nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
@ -81,8 +81,7 @@ public:
|
||||
}
|
||||
|
||||
template <class A, class S>
|
||||
explicit histogram(A&& a, S&& s)
|
||||
: axes_(std::forward<A>(a)), storage_(std::forward<S>(s)) {
|
||||
histogram(A&& a, S&& s) : axes_(std::forward<A>(a)), storage_(std::forward<S>(s)) {
|
||||
storage_.reset(detail::bincount(axes_));
|
||||
}
|
||||
|
||||
@ -125,34 +124,33 @@ public:
|
||||
not convertible to the value type accepted by the axis or passing the wrong number
|
||||
of arguments causes a throw of std::invalid_argument.
|
||||
|
||||
# Axis with multiple arguments
|
||||
**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
|
||||
**Weights**
|
||||
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
|
||||
samples and weights are used together, they can be passed in any order at the beginning
|
||||
or end of the argument list.
|
||||
*/
|
||||
//@{
|
||||
template <class... Ts>
|
||||
auto operator()(const Ts&... ts) {
|
||||
return operator()(std::forward_as_tuple(ts...));
|
||||
}
|
||||
|
||||
/// Fill histogram with values and optional weight or sample from a tuple.
|
||||
template <class... Ts>
|
||||
auto operator()(const std::tuple<Ts...>& t) {
|
||||
return detail::fill(storage_, axes_, t);
|
||||
}
|
||||
//@}
|
||||
|
||||
/// Add values of another histogram.
|
||||
template <class A, class S>
|
||||
@ -190,7 +188,6 @@ public:
|
||||
decltype(auto) at(int t, Ts... ts) const {
|
||||
return at(std::forward_as_tuple(t, ts...));
|
||||
}
|
||||
//@}
|
||||
|
||||
/// Access cell value at integral indices stored in std::tuple.
|
||||
/// @copydoc at(int t, Ts... ts)
|
||||
@ -252,12 +249,24 @@ public:
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
/// Return value iterator to the beginning of the histogram.
|
||||
iterator begin() noexcept { return storage_.begin(); }
|
||||
|
||||
/// Return value iterator to the end in the histogram.
|
||||
iterator end() noexcept { return storage_.end(); }
|
||||
|
||||
/// Return value iterator to the beginning of the histogram (read-only).
|
||||
const_iterator begin() const noexcept { return storage_.begin(); }
|
||||
|
||||
/// Return value iterator to the end in the histogram (read-only).
|
||||
const_iterator end() const noexcept { return storage_.end(); }
|
||||
|
||||
/// Return value iterator to the beginning of the histogram (read-only).
|
||||
const_iterator cbegin() const noexcept { return storage_.begin(); }
|
||||
|
||||
/// Return value iterator to the end in the histogram (read-only).
|
||||
const_iterator cend() const noexcept { return storage_.end(); }
|
||||
|
||||
private:
|
||||
axes_type axes_;
|
||||
storage_type storage_;
|
||||
|
@ -81,15 +81,15 @@ namespace accumulators {
|
||||
template <class RealType>
|
||||
template <class Archive>
|
||||
void sum<RealType>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& sum_;
|
||||
ar& cor_;
|
||||
ar& large_;
|
||||
ar& small_;
|
||||
}
|
||||
|
||||
template <class RealType>
|
||||
template <class Archive>
|
||||
void weighted_sum<RealType>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& sum_;
|
||||
ar& sum2_;
|
||||
ar& sum_of_weights_;
|
||||
ar& sum_of_weights_squared_;
|
||||
}
|
||||
|
||||
template <class RealType>
|
||||
|
@ -31,7 +31,7 @@ int main() {
|
||||
BOOST_TEST_EQ(w, 1);
|
||||
BOOST_TEST_NE(w, 2);
|
||||
|
||||
w(2);
|
||||
w += 2;
|
||||
BOOST_TEST_EQ(w.value(), 3);
|
||||
BOOST_TEST_EQ(w.variance(), 5);
|
||||
BOOST_TEST_EQ(w, w_t(3, 5));
|
||||
@ -44,20 +44,14 @@ int main() {
|
||||
// consistency: a weighted counter increased by weight 1 multiplied
|
||||
// by 2 must be the same as a weighted counter increased by weight 2
|
||||
w_t u(0);
|
||||
u(1);
|
||||
++u;
|
||||
u *= 2;
|
||||
BOOST_TEST_EQ(u, w_t(2, 4));
|
||||
|
||||
w_t v(0);
|
||||
v(2);
|
||||
v += 2;
|
||||
BOOST_TEST_EQ(u, v);
|
||||
|
||||
// consistency : a weight counter increased by a real number x
|
||||
// is the same was adding x times weight(1)
|
||||
w_t x(0);
|
||||
x += 2;
|
||||
BOOST_TEST_EQ(x, w_t(2, 2));
|
||||
|
||||
// conversion to RealType
|
||||
w_t y(1, 2);
|
||||
BOOST_TEST_NE(y, 1);
|
||||
@ -134,9 +128,9 @@ int main() {
|
||||
BOOST_TEST_EQ(bad_sum, 0); // instead of 2
|
||||
|
||||
accumulators::sum<double> sum;
|
||||
sum(); // equivalent to sum += 1
|
||||
sum(1e100); // equivalent to sum += 1e100
|
||||
sum += 1;
|
||||
++sum;
|
||||
sum += 1e100;
|
||||
++sum;
|
||||
sum += -1e100;
|
||||
BOOST_TEST_EQ(sum, 2);
|
||||
}
|
||||
@ -144,10 +138,10 @@ int main() {
|
||||
{
|
||||
accumulators::weighted_sum<accumulators::sum<double>> w;
|
||||
|
||||
w();
|
||||
w(1e100);
|
||||
w();
|
||||
w(-1e100);
|
||||
++w;
|
||||
w += 1e100;
|
||||
++w;
|
||||
w += -1e100;
|
||||
|
||||
BOOST_TEST_EQ(w.value(), 2);
|
||||
BOOST_TEST_EQ(w.variance(), 2e200);
|
||||
|
@ -158,10 +158,9 @@ int main() {
|
||||
{
|
||||
auto a = storage_adaptor<std::vector<accumulators::weighted_sum<double>>>();
|
||||
a.reset(1);
|
||||
a[0]();
|
||||
a[0](1); // rvalue weight
|
||||
const auto weight = 2;
|
||||
a[0](weight); // lvalue weight
|
||||
++a[0];
|
||||
a[0] += 1;
|
||||
a[0] += 2;
|
||||
a[0] += accumulators::weighted_sum<double>(1, 0);
|
||||
BOOST_TEST_EQ(a[0].value(), 5);
|
||||
BOOST_TEST_EQ(a[0].variance(), 6);
|
||||
|
Loading…
x
Reference in New Issue
Block a user