add boost on mac
This commit is contained in:
90
macx64/include/boost/histogram/accumulators/mean.hpp
Normal file
90
macx64/include/boost/histogram/accumulators/mean.hpp
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_ACCUMULATORS_MEAN_HPP
|
||||
#define BOOST_HISTOGRAM_ACCUMULATORS_MEAN_HPP
|
||||
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace accumulators {
|
||||
|
||||
/** Calculates mean and variance of sample.
|
||||
|
||||
Uses Welfords's incremental algorithm to improve the numerical
|
||||
stability of mean and variance computation.
|
||||
*/
|
||||
template <class RealType>
|
||||
class mean {
|
||||
public:
|
||||
mean() = default;
|
||||
mean(const std::size_t n, const RealType& mean, const RealType& variance)
|
||||
: sum_(n), mean_(mean), sum_of_deltas_squared_(variance * (sum_ - 1)) {}
|
||||
|
||||
void operator()(const RealType& x) {
|
||||
sum_ += 1;
|
||||
const auto delta = x - mean_;
|
||||
mean_ += delta / sum_;
|
||||
sum_of_deltas_squared_ += delta * (x - mean_);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
mean& operator+=(const mean<T>& rhs) {
|
||||
const auto tmp = mean_ * sum_ + static_cast<RealType>(rhs.mean_ * rhs.sum_);
|
||||
sum_ += rhs.sum_;
|
||||
mean_ = tmp / sum_;
|
||||
sum_of_deltas_squared_ += static_cast<RealType>(rhs.sum_of_deltas_squared_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
mean& operator*=(const RealType& s) {
|
||||
mean_ *= s;
|
||||
sum_of_deltas_squared_ *= s * s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator==(const mean<T>& rhs) const noexcept {
|
||||
return sum_ == rhs.sum_ && mean_ == rhs.mean_ &&
|
||||
sum_of_deltas_squared_ == rhs.sum_of_deltas_squared_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator!=(const mean<T>& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
std::size_t count() const noexcept { return sum_; }
|
||||
const RealType& value() const noexcept { return mean_; }
|
||||
RealType variance() const { return sum_of_deltas_squared_ / (sum_ - 1); }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */);
|
||||
|
||||
private:
|
||||
std::size_t sum_ = 0;
|
||||
RealType mean_ = 0, sum_of_deltas_squared_ = 0;
|
||||
};
|
||||
|
||||
} // namespace accumulators
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
namespace std {
|
||||
template <class T, class U>
|
||||
/// Specialization for boost::histogram::accumulators::mean.
|
||||
struct common_type<boost::histogram::accumulators::mean<T>,
|
||||
boost::histogram::accumulators::mean<U>> {
|
||||
using type = boost::histogram::accumulators::mean<common_type_t<T, U>>;
|
||||
};
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
#endif
|
||||
52
macx64/include/boost/histogram/accumulators/ostream.hpp
Normal file
52
macx64/include/boost/histogram/accumulators/ostream.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_ACCUMULATORS_OSTREAM_HPP
|
||||
#define BOOST_HISTOGRAM_ACCUMULATORS_OSTREAM_HPP
|
||||
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <iosfwd>
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace accumulators {
|
||||
template <typename CharT, typename Traits, typename W>
|
||||
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
|
||||
const sum<W>& x) {
|
||||
os << "sum(" << x.large() << " + " << x.small() << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits, typename W>
|
||||
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
|
||||
const weighted_sum<W>& x) {
|
||||
os << "weighted_sum(" << x.value() << ", " << x.variance() << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits, typename W>
|
||||
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
|
||||
const mean<W>& x) {
|
||||
os << "mean(" << x.count() << ", " << x.value() << ", " << x.variance() << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits, typename W>
|
||||
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
|
||||
const weighted_mean<W>& x) {
|
||||
os << "weighted_mean(" << x.sum_of_weights() << ", " << x.value() << ", "
|
||||
<< x.variance() << ")";
|
||||
return os;
|
||||
}
|
||||
} // namespace accumulators
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
#endif
|
||||
107
macx64/include/boost/histogram/accumulators/sum.hpp
Normal file
107
macx64/include/boost/histogram/accumulators/sum.hpp
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_ACCUMULATORS_SUM_HPP
|
||||
#define BOOST_HISTOGRAM_ACCUMULATORS_SUM_HPP
|
||||
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace accumulators {
|
||||
|
||||
/**
|
||||
Uses Neumaier algorithm to compute accurate sums.
|
||||
|
||||
The algorithm uses memory for two floats and is three to
|
||||
five times slower compared to a simple floating point
|
||||
number used to accumulate a sum, but the relative error
|
||||
of the sum is at the level of the machine precision,
|
||||
independent of the number of samples.
|
||||
|
||||
A. Neumaier, Zeitschrift fuer Angewandte Mathematik
|
||||
und Mechanik 54 (1974) 39-51.
|
||||
*/
|
||||
template <typename RealType>
|
||||
class sum {
|
||||
public:
|
||||
sum() = default;
|
||||
|
||||
/// Initialize sum to value
|
||||
explicit sum(const RealType& value) noexcept : large_(value) {}
|
||||
|
||||
/// Set sum to value
|
||||
sum& operator=(const RealType& value) noexcept {
|
||||
large_ = value;
|
||||
small_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Increment sum by one
|
||||
sum& operator++() { return operator+=(1); }
|
||||
|
||||
/// 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
|
||||
small_ += (value - temp) + large_;
|
||||
large_ = temp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Scale by value
|
||||
sum& operator*=(const RealType& value) {
|
||||
large_ *= value;
|
||||
small_ *= value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator==(const sum<T>& rhs) const noexcept {
|
||||
return large_ == rhs.large_ && small_ == rhs.small_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator!=(const T& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
/// 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 large_ + small_; }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */);
|
||||
|
||||
private:
|
||||
RealType large_ = RealType();
|
||||
RealType small_ = RealType();
|
||||
};
|
||||
|
||||
} // namespace accumulators
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
namespace std {
|
||||
template <class T, class U>
|
||||
struct common_type<boost::histogram::accumulators::sum<T>,
|
||||
boost::histogram::accumulators::sum<U>> {
|
||||
using type = boost::histogram::accumulators::sum<common_type_t<T, U>>;
|
||||
};
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
#endif
|
||||
106
macx64/include/boost/histogram/accumulators/weighted_mean.hpp
Normal file
106
macx64/include/boost/histogram/accumulators/weighted_mean.hpp
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_ACCUMULATORS_WEIGHTED_MEAN_HPP
|
||||
#define BOOST_HISTOGRAM_ACCUMULATORS_WEIGHTED_MEAN_HPP
|
||||
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace accumulators {
|
||||
|
||||
/**
|
||||
Calculates mean and variance of weighted sample.
|
||||
|
||||
Uses West's incremental algorithm to improve numerical stability
|
||||
of mean and variance computation.
|
||||
*/
|
||||
template <typename RealType>
|
||||
class weighted_mean {
|
||||
public:
|
||||
weighted_mean() = default;
|
||||
weighted_mean(const RealType& wsum, const RealType& wsum2, const RealType& mean,
|
||||
const RealType& variance)
|
||||
: sum_of_weights_(wsum)
|
||||
, sum_of_weights_squared_(wsum2)
|
||||
, weighted_mean_(mean)
|
||||
, sum_of_weighted_deltas_squared_(
|
||||
variance * (sum_of_weights_ - sum_of_weights_squared_ / sum_of_weights_)) {}
|
||||
|
||||
void operator()(const RealType& x) { operator()(1, x); }
|
||||
|
||||
void operator()(const RealType& w, const RealType& x) {
|
||||
sum_of_weights_ += w;
|
||||
sum_of_weights_squared_ += w * w;
|
||||
const auto delta = x - weighted_mean_;
|
||||
weighted_mean_ += w * delta / sum_of_weights_;
|
||||
sum_of_weighted_deltas_squared_ += w * delta * (x - weighted_mean_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
weighted_mean& operator+=(const weighted_mean<T>& rhs) {
|
||||
const auto tmp = weighted_mean_ * sum_of_weights_ +
|
||||
static_cast<RealType>(rhs.weighted_mean_ * rhs.sum_of_weights_);
|
||||
sum_of_weights_ += static_cast<RealType>(rhs.sum_of_weights_);
|
||||
sum_of_weights_squared_ += static_cast<RealType>(rhs.sum_of_weights_squared_);
|
||||
weighted_mean_ = tmp / sum_of_weights_;
|
||||
sum_of_weighted_deltas_squared_ +=
|
||||
static_cast<RealType>(rhs.sum_of_weighted_deltas_squared_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
weighted_mean& operator*=(const RealType& s) {
|
||||
weighted_mean_ *= s;
|
||||
sum_of_weighted_deltas_squared_ *= s * s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator==(const weighted_mean<T>& rhs) const noexcept {
|
||||
return sum_of_weights_ == rhs.sum_of_weights_ &&
|
||||
sum_of_weights_squared_ == rhs.sum_of_weights_squared_ &&
|
||||
weighted_mean_ == rhs.weighted_mean_ &&
|
||||
sum_of_weighted_deltas_squared_ == rhs.sum_of_weighted_deltas_squared_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator!=(const T& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
const RealType& sum_of_weights() const noexcept { return sum_of_weights_; }
|
||||
const RealType& value() const noexcept { return weighted_mean_; }
|
||||
RealType variance() const {
|
||||
return sum_of_weighted_deltas_squared_ /
|
||||
(sum_of_weights_ - sum_of_weights_squared_ / sum_of_weights_);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */);
|
||||
|
||||
private:
|
||||
RealType sum_of_weights_ = RealType(), sum_of_weights_squared_ = RealType(),
|
||||
weighted_mean_ = RealType(), sum_of_weighted_deltas_squared_ = RealType();
|
||||
};
|
||||
|
||||
} // namespace accumulators
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
namespace std {
|
||||
template <class T, class U>
|
||||
/// Specialization for boost::histogram::accumulators::weighted_mean.
|
||||
struct common_type<boost::histogram::accumulators::weighted_mean<T>,
|
||||
boost::histogram::accumulators::weighted_mean<U>> {
|
||||
using type = boost::histogram::accumulators::weighted_mean<common_type_t<T, U>>;
|
||||
};
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
#endif
|
||||
112
macx64/include/boost/histogram/accumulators/weighted_sum.hpp
Normal file
112
macx64/include/boost/histogram/accumulators/weighted_sum.hpp
Normal file
@@ -0,0 +1,112 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_ACCUMULATORS_WEIGHTED_SUM_HPP
|
||||
#define BOOST_HISTOGRAM_ACCUMULATORS_WEIGHTED_SUM_HPP
|
||||
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace accumulators {
|
||||
|
||||
/// Holds sum of weights and its variance estimate
|
||||
template <typename RealType>
|
||||
class weighted_sum {
|
||||
public:
|
||||
weighted_sum() = default;
|
||||
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_of_weights_(value), sum_of_weights_squared_(variance) {}
|
||||
|
||||
/// Increment by one.
|
||||
weighted_sum& operator++() { return operator+=(1); }
|
||||
|
||||
/// Increment by value.
|
||||
template <typename T>
|
||||
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_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_of_weights_ *= x;
|
||||
sum_of_weights_squared_ *= x * x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const RealType& rhs) const noexcept {
|
||||
return sum_of_weights_ == rhs && sum_of_weights_squared_ == rhs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator==(const weighted_sum<T>& rhs) const noexcept {
|
||||
return sum_of_weights_ == rhs.sum_of_weights_ &&
|
||||
sum_of_weights_squared_ == rhs.sum_of_weights_squared_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator!=(const T& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
/// 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 <class T>
|
||||
explicit operator T() const {
|
||||
return static_cast<T>(sum_of_weights_);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned /* version */);
|
||||
|
||||
private:
|
||||
RealType sum_of_weights_ = RealType();
|
||||
RealType sum_of_weights_squared_ = RealType();
|
||||
};
|
||||
|
||||
} // namespace accumulators
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
namespace std {
|
||||
template <class T, class U>
|
||||
struct common_type<boost::histogram::accumulators::weighted_sum<T>,
|
||||
boost::histogram::accumulators::weighted_sum<U>> {
|
||||
using type = boost::histogram::accumulators::weighted_sum<common_type_t<T, U>>;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct common_type<boost::histogram::accumulators::weighted_sum<T>, U> {
|
||||
using type = boost::histogram::accumulators::weighted_sum<common_type_t<T, U>>;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct common_type<T, boost::histogram::accumulators::weighted_sum<U>> {
|
||||
using type = boost::histogram::accumulators::weighted_sum<common_type_t<T, U>>;
|
||||
};
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
#endif
|
||||
98
macx64/include/boost/histogram/algorithm/project.hpp
Normal file
98
macx64/include/boost/histogram/algorithm/project.hpp
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_ALGORITHM_PROJECT_HPP
|
||||
#define BOOST_HISTOGRAM_ALGORITHM_PROJECT_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/histogram.hpp>
|
||||
#include <boost/histogram/indexed.hpp>
|
||||
#include <boost/histogram/unsafe_access.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/mp11/set.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace algorithm {
|
||||
|
||||
/**
|
||||
Returns a lower-dimensional histogram, summing over removed axes.
|
||||
|
||||
Arguments are the source histogram and compile-time numbers, the remaining indices of
|
||||
the axes. Returns a new histogram which only contains the subset of axes. The source
|
||||
histogram is summed over the removed axes.
|
||||
*/
|
||||
template <class A, class S, unsigned N, typename... Ns>
|
||||
auto project(const histogram<A, S>& h, std::integral_constant<unsigned, N>, Ns...) {
|
||||
using LN = mp11::mp_list<std::integral_constant<unsigned, N>, Ns...>;
|
||||
static_assert(mp11::mp_is_set<LN>::value, "indices must be unique");
|
||||
|
||||
const auto& old_axes = unsafe_access::axes(h);
|
||||
auto axes = detail::static_if<detail::is_tuple<A>>(
|
||||
[&](const auto& old_axes) {
|
||||
return std::make_tuple(std::get<N>(old_axes), std::get<Ns::value>(old_axes)...);
|
||||
},
|
||||
[&](const auto& old_axes) {
|
||||
return detail::remove_cvref_t<decltype(old_axes)>(
|
||||
{old_axes[N], old_axes[Ns::value]...});
|
||||
},
|
||||
old_axes);
|
||||
|
||||
const auto& old_storage = unsafe_access::storage(h);
|
||||
using A2 = decltype(axes);
|
||||
auto result = histogram<A2, S>(std::move(axes), detail::make_default(old_storage));
|
||||
auto idx = detail::make_stack_buffer<int>(unsafe_access::axes(result));
|
||||
for (auto x : indexed(h, coverage::all)) {
|
||||
auto i = idx.begin();
|
||||
mp11::mp_for_each<LN>([&i, &x](auto J) { *i++ = x.index(J); });
|
||||
result.at(idx) += *x;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a lower-dimensional histogram, summing over removed axes.
|
||||
|
||||
This version accepts a source histogram and an iterable range containing the remaining
|
||||
indices.
|
||||
*/
|
||||
template <class A, class S, class Iterable, class = detail::requires_iterable<Iterable>>
|
||||
auto project(const histogram<A, S>& h, const Iterable& c) {
|
||||
static_assert(detail::is_sequence_of_any_axis<A>::value,
|
||||
"this version of project requires histogram with non-static axes");
|
||||
|
||||
const auto& old_axes = unsafe_access::axes(h);
|
||||
auto axes = detail::make_default(old_axes);
|
||||
axes.reserve(c.size());
|
||||
auto seen = detail::make_stack_buffer<bool>(old_axes, false);
|
||||
for (auto d : c) {
|
||||
if (seen[d]) BOOST_THROW_EXCEPTION(std::invalid_argument("indices must be unique"));
|
||||
seen[d] = true;
|
||||
axes.emplace_back(old_axes[d]);
|
||||
}
|
||||
|
||||
const auto& old_storage = unsafe_access::storage(h);
|
||||
auto result = histogram<A, S>(std::move(axes), detail::make_default(old_storage));
|
||||
auto idx = detail::make_stack_buffer<int>(unsafe_access::axes(result));
|
||||
for (auto x : indexed(h, coverage::all)) {
|
||||
auto i = idx.begin();
|
||||
for (auto d : c) *i++ = x.index(d);
|
||||
result.at(idx) += *x;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
222
macx64/include/boost/histogram/algorithm/reduce.hpp
Normal file
222
macx64/include/boost/histogram/algorithm/reduce.hpp
Normal file
@@ -0,0 +1,222 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_ALGORITHM_REDUCE_HPP
|
||||
#define BOOST_HISTOGRAM_ALGORITHM_REDUCE_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/detail/axes.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/histogram/indexed.hpp>
|
||||
#include <boost/histogram/unsafe_access.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace algorithm {
|
||||
|
||||
/**
|
||||
Option type returned by the helper functions shrink_and_rebin(), shrink(), rebin().
|
||||
*/
|
||||
struct reduce_option {
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
unsigned iaxis = 0;
|
||||
double lower, upper;
|
||||
unsigned merge = 0;
|
||||
|
||||
reduce_option() noexcept = default;
|
||||
|
||||
reduce_option(unsigned i, double l, double u, unsigned m)
|
||||
: iaxis(i), lower(l), upper(u), merge(m) {
|
||||
if (lower == upper)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("lower != upper required"));
|
||||
if (merge == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("merge > 0 required"));
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
Shrink and rebin option.
|
||||
|
||||
@param iaxis which axis to operate on.
|
||||
@param lower lowest bound that should be kept.
|
||||
@param upper highest bound that should be kept. If upper is inside bin interval, the
|
||||
whole interval is removed.
|
||||
@param merge how many adjacent bins to merge into one.
|
||||
*/
|
||||
inline auto shrink_and_rebin(unsigned iaxis, double lower, double upper, unsigned merge) {
|
||||
return reduce_option{iaxis, lower, upper, merge};
|
||||
}
|
||||
|
||||
/**
|
||||
Shrink option.
|
||||
|
||||
@param iaxis which axis to operate on.
|
||||
@param lower lowest bound that should be kept.
|
||||
@param upper highest bound that should be kept. If upper is inside bin interval, the
|
||||
whole interval is removed.
|
||||
*/
|
||||
inline auto shrink(unsigned iaxis, double lower, double upper) {
|
||||
return reduce_option{iaxis, lower, upper, 1};
|
||||
}
|
||||
|
||||
/**
|
||||
Rebin option.
|
||||
|
||||
@param iaxis which axis to operate on.
|
||||
@param merge how many adjacent bins to merge into one.
|
||||
*/
|
||||
inline auto rebin(unsigned iaxis, unsigned merge) {
|
||||
return reduce_option{iaxis, std::numeric_limits<double>::quiet_NaN(),
|
||||
std::numeric_limits<double>::quiet_NaN(), merge};
|
||||
}
|
||||
|
||||
/**
|
||||
Convenience overload for single axis.
|
||||
|
||||
@param lower lowest bound that should be kept.
|
||||
@param upper highest bound that should be kept. If upper is inside bin interval, the
|
||||
whole interval is removed.
|
||||
@param merge how many adjacent bins to merge into one.
|
||||
*/
|
||||
inline auto shrink_and_rebin(double lower, double upper, unsigned merge) {
|
||||
return shrink_and_rebin(0, lower, upper, merge);
|
||||
}
|
||||
|
||||
/**
|
||||
Convenience overload for single axis.
|
||||
|
||||
@param lower lowest bound that should be kept.
|
||||
@param upper highest bound that should be kept. If upper is inside bin interval, the
|
||||
whole interval is removed.
|
||||
*/
|
||||
inline auto shrink(double lower, double upper) { return shrink(0, lower, upper); }
|
||||
|
||||
/**
|
||||
Convenience overload for single axis.
|
||||
|
||||
@param merge how many adjacent bins to merge into one.
|
||||
*/
|
||||
inline auto rebin(unsigned merge) { return rebin(0, merge); }
|
||||
|
||||
/**
|
||||
Shrink and/or rebin axes of a histogram.
|
||||
|
||||
Returns the reduced copy of the histogram.
|
||||
|
||||
@param hist original histogram.
|
||||
@param options iterable sequence of reduce_options, generated by shrink_and_rebin(),
|
||||
shrink(), and rebin().
|
||||
*/
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
template <class Histogram, class Iterable, class = detail::requires_iterable<Iterable>>
|
||||
#else
|
||||
template <class Histogram, class Iterable>
|
||||
#endif
|
||||
decltype(auto) reduce(const Histogram& hist, const Iterable& options) {
|
||||
const auto& old_axes = unsafe_access::axes(hist);
|
||||
|
||||
struct option_item : reduce_option {
|
||||
int begin, end;
|
||||
};
|
||||
|
||||
auto opts = detail::make_stack_buffer<option_item>(old_axes);
|
||||
for (const auto& o : options) {
|
||||
auto& oi = opts[o.iaxis];
|
||||
if (oi.merge > 0) // did we already set the option for this axis?
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("indices must be unique"));
|
||||
oi.lower = o.lower;
|
||||
oi.upper = o.upper;
|
||||
oi.merge = o.merge;
|
||||
}
|
||||
|
||||
// make new axes container with default-constructed axis instances
|
||||
auto axes = detail::make_default(old_axes);
|
||||
detail::static_if<detail::is_tuple<decltype(axes)>>(
|
||||
[](auto&, const auto&) {},
|
||||
[](auto& axes, const auto& old_axes) {
|
||||
axes.reserve(old_axes.size());
|
||||
for (const auto& a : old_axes) axes.emplace_back(detail::make_default(a));
|
||||
},
|
||||
axes, old_axes);
|
||||
|
||||
// override default-constructed axis instances with modified instances
|
||||
unsigned iaxis = 0;
|
||||
hist.for_each_axis([&](const auto& a) {
|
||||
using T = detail::remove_cvref_t<decltype(a)>;
|
||||
|
||||
auto& o = opts[iaxis];
|
||||
o.begin = 0;
|
||||
o.end = a.size();
|
||||
if (o.merge > 0) { // option is set?
|
||||
if (o.lower < o.upper) {
|
||||
while (o.begin != o.end && a.value(o.begin) < o.lower) ++o.begin;
|
||||
while (o.end != o.begin && a.value(o.end - 1) >= o.upper) --o.end;
|
||||
} else if (o.lower > o.upper) {
|
||||
// for inverted axis::regular
|
||||
while (o.begin != o.end && a.value(o.begin) > o.lower) ++o.begin;
|
||||
while (o.end != o.begin && a.value(o.end - 1) <= o.upper) --o.end;
|
||||
}
|
||||
o.end -= (o.end - o.begin) % o.merge;
|
||||
auto a2 = T(a, o.begin, o.end, o.merge);
|
||||
axis::get<T>(detail::axis_get(axes, iaxis)) = a2;
|
||||
} else {
|
||||
o.merge = 1;
|
||||
axis::get<T>(detail::axis_get(axes, iaxis)) = a;
|
||||
}
|
||||
++iaxis;
|
||||
});
|
||||
|
||||
auto storage = detail::make_default(unsafe_access::storage(hist));
|
||||
auto result = Histogram(std::move(axes), std::move(storage));
|
||||
|
||||
auto idx = detail::make_stack_buffer<int>(unsafe_access::axes(result));
|
||||
for (auto x : indexed(hist, coverage::all)) {
|
||||
auto i = idx.begin();
|
||||
auto o = opts.begin();
|
||||
for (auto j : x.indices()) {
|
||||
*i = (j - o->begin);
|
||||
if (*i <= -1)
|
||||
*i = -1;
|
||||
else {
|
||||
*i /= o->merge;
|
||||
const int end = (o->end - o->begin) / o->merge;
|
||||
if (*i > end) *i = end;
|
||||
}
|
||||
++i;
|
||||
++o;
|
||||
}
|
||||
result.at(idx) += *x;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Shrink and/or rebin axes of a histogram.
|
||||
|
||||
Returns the modified copy.
|
||||
|
||||
@param hist original histogram.
|
||||
@param opt reduce option generated by shrink_and_rebin(), shrink(), and rebin().
|
||||
@param opts more reduce_options.
|
||||
*/
|
||||
template <class Histogram, class... Ts>
|
||||
decltype(auto) reduce(const Histogram& hist, const reduce_option& opt, Ts&&... opts) {
|
||||
// this must be in one line, because any of the ts could be a temporary
|
||||
return reduce(hist, std::initializer_list<reduce_option>{opt, opts...});
|
||||
}
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
41
macx64/include/boost/histogram/algorithm/sum.hpp
Normal file
41
macx64/include/boost/histogram/algorithm/sum.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_ALGORITHM_SUM_HPP
|
||||
#define BOOST_HISTOGRAM_ALGORITHM_SUM_HPP
|
||||
|
||||
#include <boost/histogram/accumulators/sum.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <numeric>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace algorithm {
|
||||
/** Compute the sum over all histogram cells, including underflow/overflow bins.
|
||||
|
||||
If the value type of the histogram is an integral or floating point type,
|
||||
boost::accumulators::sum<double> is used to compute the sum, else the original value
|
||||
type is used. Compilation fails, if the value type does not support operator+=.
|
||||
|
||||
Return type is double if the value type of the histogram is integral or floating point,
|
||||
and the original value type otherwise.
|
||||
*/
|
||||
template <class A, class S>
|
||||
auto sum(const histogram<A, S>& h) {
|
||||
using T = typename histogram<A, S>::value_type;
|
||||
using Sum = mp11::mp_if<std::is_arithmetic<T>, accumulators::sum<double>, T>;
|
||||
Sum sum;
|
||||
for (auto x : h) sum += x;
|
||||
using R = mp11::mp_if<std::is_arithmetic<T>, double, T>;
|
||||
return static_cast<R>(sum);
|
||||
}
|
||||
} // namespace algorithm
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
16
macx64/include/boost/histogram/axis.hpp
Normal file
16
macx64/include/boost/histogram/axis.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_HPP
|
||||
|
||||
#include <boost/histogram/axis/category.hpp>
|
||||
#include <boost/histogram/axis/integer.hpp>
|
||||
#include <boost/histogram/axis/regular.hpp>
|
||||
#include <boost/histogram/axis/variable.hpp>
|
||||
#include <boost/histogram/axis/variant.hpp>
|
||||
|
||||
#endif
|
||||
184
macx64/include/boost/histogram/axis/category.hpp
Normal file
184
macx64/include/boost/histogram/axis/category.hpp
Normal file
@@ -0,0 +1,184 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_CATEGORY_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_CATEGORY_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/compressed_pair.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
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.
|
||||
|
||||
@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.
|
||||
*/
|
||||
template <class Value, class MetaData, class Options, class Allocator>
|
||||
class category : public iterator_mixin<category<Value, MetaData, Options, Allocator>> {
|
||||
using value_type = Value;
|
||||
using metadata_type = detail::replace_default<MetaData, std::string>;
|
||||
using options_type = detail::replace_default<Options, option::overflow_t>;
|
||||
static_assert(!options_type::test(option::underflow),
|
||||
"category axis cannot have underflow");
|
||||
static_assert(!options_type::test(option::circular),
|
||||
"category axis cannot be circular");
|
||||
static_assert(!options_type::test(option::growth) ||
|
||||
!options_type::test(option::overflow),
|
||||
"growing category axis cannot have overflow");
|
||||
using allocator_type = Allocator;
|
||||
using vector_type = std::vector<value_type, allocator_type>;
|
||||
|
||||
public:
|
||||
explicit category(allocator_type alloc = {}) : vec_meta_(vector_type(alloc)) {}
|
||||
|
||||
/** Construct from 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.
|
||||
* \param alloc allocator instance to use.
|
||||
*/
|
||||
template <class It, class = detail::requires_iterator<It>>
|
||||
category(It begin, It end, metadata_type meta = {}, allocator_type alloc = {})
|
||||
: vec_meta_(vector_type(begin, end, alloc), std::move(meta)) {
|
||||
if (size() == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
|
||||
}
|
||||
|
||||
/** Construct axis from iterable sequence of unique values.
|
||||
*
|
||||
* \param iterable sequence of unique values.
|
||||
* \param meta description of the axis.
|
||||
* \param alloc allocator instance to use.
|
||||
*/
|
||||
template <class C, class = detail::requires_iterable<C>>
|
||||
category(const C& iterable, metadata_type meta = {}, allocator_type alloc = {})
|
||||
: category(std::begin(iterable), std::end(iterable), std::move(meta),
|
||||
std::move(alloc)) {}
|
||||
|
||||
/** Construct axis from an 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.
|
||||
*/
|
||||
template <class U>
|
||||
category(std::initializer_list<U> list, metadata_type meta = {},
|
||||
allocator_type alloc = {})
|
||||
: category(list.begin(), list.end(), std::move(meta), std::move(alloc)) {}
|
||||
|
||||
/// Constructor used by algorithm::reduce to shrink and rebin.
|
||||
category(const category& src, index_type begin, index_type end, unsigned merge)
|
||||
: category(src.vec_meta_.first().begin() + begin,
|
||||
src.vec_meta_.first().begin() + end, src.metadata()) {
|
||||
if (merge > 1)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("cannot merge bins for category axis"));
|
||||
}
|
||||
|
||||
/// Return index for value argument.
|
||||
index_type index(const value_type& x) const noexcept {
|
||||
const auto beg = vec_meta_.first().begin();
|
||||
const auto end = vec_meta_.first().end();
|
||||
return static_cast<index_type>(std::distance(beg, std::find(beg, end, x)));
|
||||
}
|
||||
|
||||
/// Returns index and shift (if axis has grown) for the passed argument.
|
||||
auto update(const value_type& x) {
|
||||
const auto i = index(x);
|
||||
if (i < size()) return std::make_pair(i, 0);
|
||||
vec_meta_.first().emplace_back(x);
|
||||
return std::make_pair(i, -1);
|
||||
}
|
||||
|
||||
/// 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];
|
||||
}
|
||||
|
||||
/// Return value for index argument.
|
||||
decltype(auto) bin(index_type idx) const noexcept { return value(idx); }
|
||||
|
||||
/// Returns the number of bins, without over- or underflow.
|
||||
index_type size() const noexcept {
|
||||
return static_cast<index_type>(vec_meta_.first().size());
|
||||
}
|
||||
/// Returns the options.
|
||||
static constexpr unsigned options() noexcept { return options_type::value; }
|
||||
/// Returns reference to metadata.
|
||||
metadata_type& metadata() noexcept { return vec_meta_.second(); }
|
||||
/// Returns reference to const metadata.
|
||||
const metadata_type& metadata() const noexcept { return vec_meta_.second(); }
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
bool operator==(const category<V, M, O, A>& o) const noexcept {
|
||||
const auto& a = vec_meta_.first();
|
||||
const auto& b = o.vec_meta_.first();
|
||||
return std::equal(a.begin(), a.end(), b.begin(), b.end()) &&
|
||||
detail::relaxed_equal(metadata(), o.metadata());
|
||||
}
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
bool operator!=(const category<V, M, O, A>& o) const noexcept {
|
||||
return !operator==(o);
|
||||
}
|
||||
|
||||
auto get_allocator() const { return vec_meta_.first().get_allocator(); }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
|
||||
private:
|
||||
detail::compressed_pair<vector_type, metadata_type> vec_meta_;
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
friend class category;
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
|
||||
template <class T>
|
||||
category(std::initializer_list<T>)->category<T>;
|
||||
|
||||
category(std::initializer_list<const char*>)->category<std::string>;
|
||||
|
||||
template <class T>
|
||||
category(std::initializer_list<T>, const char*)->category<T>;
|
||||
|
||||
template <class T, class M>
|
||||
category(std::initializer_list<T>, const M&)->category<T, M>;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
194
macx64/include/boost/histogram/axis/integer.hpp
Normal file
194
macx64/include/boost/histogram/axis/integer.hpp
Normal file
@@ -0,0 +1,194 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_INTEGER_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_INTEGER_HPP
|
||||
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/compressed_pair.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
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.
|
||||
|
||||
@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 (all values allowed).
|
||||
*/
|
||||
template <class Value, class MetaData, class Options>
|
||||
class integer : public iterator_mixin<integer<Value, MetaData, Options>> {
|
||||
static_assert(std::is_integral<Value>::value || std::is_floating_point<Value>::value,
|
||||
"integer axis requires type floating point or integral type");
|
||||
|
||||
using value_type = Value;
|
||||
using local_index_type = std::conditional_t<std::is_integral<value_type>::value,
|
||||
index_type, real_index_type>;
|
||||
|
||||
using metadata_type = detail::replace_default<MetaData, std::string>;
|
||||
using options_type =
|
||||
detail::replace_default<Options, decltype(option::underflow | option::overflow)>;
|
||||
|
||||
static_assert(!options_type::test(option::circular) ||
|
||||
std::is_floating_point<value_type>::value ||
|
||||
!options_type::test(option::overflow),
|
||||
"integer axis with integral type cannot have overflow");
|
||||
|
||||
public:
|
||||
constexpr integer() = default;
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
integer(value_type start, value_type stop, metadata_type meta = {})
|
||||
: size_meta_(static_cast<index_type>(stop - start), std::move(meta)), min_(start) {
|
||||
if (stop <= start) BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
|
||||
}
|
||||
|
||||
/// Constructor used by algorithm::reduce to shrink and rebin.
|
||||
integer(const integer& src, index_type begin, index_type end, unsigned merge)
|
||||
: integer(src.value(begin), src.value(end), src.metadata()) {
|
||||
if (merge > 1)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("cannot merge bins for integer axis"));
|
||||
if (options_type::test(option::circular) && !(begin == 0 && end == src.size()))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("cannot shrink circular axis"));
|
||||
}
|
||||
|
||||
/// Return index for value argument.
|
||||
index_type index(value_type x) const noexcept {
|
||||
return index_impl(std::is_floating_point<value_type>(), x);
|
||||
}
|
||||
|
||||
/// Returns index and shift (if axis has grown) for the passed argument.
|
||||
auto update(value_type x) noexcept {
|
||||
auto impl = [this](long x) {
|
||||
const auto i = x - min_;
|
||||
if (i >= 0) {
|
||||
const auto k = static_cast<axis::index_type>(i);
|
||||
if (k < size()) return std::make_pair(k, 0);
|
||||
const auto n = k - size() + 1;
|
||||
size_meta_.first() += n;
|
||||
return std::make_pair(k, -n);
|
||||
}
|
||||
const auto k = static_cast<axis::index_type>(
|
||||
detail::static_if<std::is_floating_point<value_type>>(
|
||||
[](auto x) { return std::floor(x); }, [](auto x) { return x; }, i));
|
||||
min_ += k;
|
||||
size_meta_.first() -= k;
|
||||
return std::make_pair(0, -k);
|
||||
};
|
||||
|
||||
return detail::static_if<std::is_floating_point<value_type>>(
|
||||
[this, impl](auto x) {
|
||||
if (std::isfinite(x)) return impl(static_cast<long>(std::floor(x)));
|
||||
// this->size() is workaround for gcc-5 bug
|
||||
return std::make_pair(x < 0 ? -1 : this->size(), 0);
|
||||
},
|
||||
impl, x);
|
||||
}
|
||||
|
||||
/// Return value for index argument.
|
||||
value_type value(local_index_type i) const noexcept {
|
||||
if (!options_type::test(option::circular)) {
|
||||
if (i < 0) return detail::lowest<value_type>();
|
||||
if (i > size()) { return detail::highest<value_type>(); }
|
||||
}
|
||||
return min_ + i;
|
||||
}
|
||||
|
||||
/// Return bin for index argument.
|
||||
decltype(auto) bin(index_type idx) const noexcept {
|
||||
return detail::static_if<std::is_floating_point<local_index_type>>(
|
||||
[this](auto idx) { return interval_view<integer>(*this, idx); },
|
||||
[this](auto idx) { return this->value(idx); }, idx);
|
||||
}
|
||||
|
||||
/// Returns the number of bins, without over- or underflow.
|
||||
index_type size() const noexcept { return size_meta_.first(); }
|
||||
/// Returns the options.
|
||||
static constexpr unsigned options() noexcept { return options_type::value; }
|
||||
/// Returns reference to metadata.
|
||||
metadata_type& metadata() noexcept { return size_meta_.second(); }
|
||||
/// Returns reference to const metadata.
|
||||
const metadata_type& metadata() const noexcept { return size_meta_.second(); }
|
||||
|
||||
template <class V, class M, class O>
|
||||
bool operator==(const integer<V, M, O>& o) const noexcept {
|
||||
return size() == o.size() && detail::relaxed_equal(metadata(), o.metadata()) &&
|
||||
min_ == o.min_;
|
||||
}
|
||||
|
||||
template <class V, class M, class O>
|
||||
bool operator!=(const integer<V, M, O>& o) const noexcept {
|
||||
return !operator==(o);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
|
||||
private:
|
||||
index_type index_impl(std::false_type, int x) const noexcept {
|
||||
const auto z = x - min_;
|
||||
if (options_type::test(option::circular))
|
||||
return static_cast<index_type>(z - std::floor(float(z) / size()) * size());
|
||||
if (z < size()) return z >= 0 ? z : -1;
|
||||
return size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
index_type index_impl(std::true_type, T x) const noexcept {
|
||||
// need to handle NaN, cannot simply cast to int and call int-implementation
|
||||
const auto z = x - min_;
|
||||
if (options_type::test(option::circular)) {
|
||||
if (std::isfinite(z))
|
||||
return static_cast<index_type>(std::floor(z) - std::floor(z / size()) * size());
|
||||
} else if (z < size()) {
|
||||
return z >= 0 ? static_cast<index_type>(z) : -1;
|
||||
}
|
||||
return size();
|
||||
}
|
||||
|
||||
detail::compressed_pair<index_type, metadata_type> size_meta_{0};
|
||||
value_type min_{0};
|
||||
|
||||
template <class V, class M, class O>
|
||||
friend class integer;
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
|
||||
template <class T>
|
||||
integer(T, T)->integer<detail::convert_integer<T, index_type>>;
|
||||
|
||||
template <class T>
|
||||
integer(T, T, const char*)->integer<detail::convert_integer<T, index_type>>;
|
||||
|
||||
template <class T, class M>
|
||||
integer(T, T, M)->integer<detail::convert_integer<T, index_type>, M>;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
54
macx64/include/boost/histogram/axis/interval_view.hpp
Normal file
54
macx64/include/boost/histogram/axis/interval_view.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2015-2019 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_INTERVAL_VIEW_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_INTERVAL_VIEW_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
/**
|
||||
Lightweight bin view.
|
||||
|
||||
Represents the current bin interval.
|
||||
*/
|
||||
template <typename Axis>
|
||||
class interval_view {
|
||||
public:
|
||||
interval_view(const Axis& axis, int idx) : axis_(axis), idx_(idx) {}
|
||||
// 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 <typename BinType>
|
||||
bool operator==(const BinType& rhs) const noexcept {
|
||||
return lower() == rhs.lower() && upper() == rhs.upper();
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
bool operator!=(const BinType& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
const Axis& axis_;
|
||||
const int idx_;
|
||||
};
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
74
macx64/include/boost/histogram/axis/iterator.hpp
Normal file
74
macx64/include/boost/histogram/axis/iterator.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_ITERATOR_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_ITERATOR_HPP
|
||||
|
||||
#include <boost/histogram/axis/interval_view.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
template <typename Axis>
|
||||
class iterator
|
||||
: public boost::iterator_adaptor<iterator<Axis>, int,
|
||||
decltype(std::declval<const Axis&>().bin(0)),
|
||||
std::random_access_iterator_tag,
|
||||
decltype(std::declval<const Axis&>().bin(0)), int> {
|
||||
public:
|
||||
explicit iterator(const Axis& axis, int idx)
|
||||
: iterator::iterator_adaptor_(idx), axis_(axis) {}
|
||||
|
||||
protected:
|
||||
bool equal(const iterator& other) const noexcept {
|
||||
return &axis_ == &other.axis_ && this->base() == other.base();
|
||||
}
|
||||
|
||||
decltype(auto) dereference() const { return axis_.bin(this->base()); }
|
||||
|
||||
private:
|
||||
const Axis& axis_;
|
||||
friend class boost::iterator_core_access;
|
||||
};
|
||||
|
||||
/// Uses CRTP to inject iterator logic into Derived.
|
||||
template <typename Derived>
|
||||
class iterator_mixin {
|
||||
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());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
82
macx64/include/boost/histogram/axis/option.hpp
Normal file
82
macx64/include/boost/histogram/axis/option.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright 2015-2019 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_OPTION_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_OPTION_HPP
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
\file option.hpp Options for builtin axis types.
|
||||
|
||||
Options `circular` and `growth` are mutually exclusive.
|
||||
Options `circular` and `underflow` are mutually exclusive.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
namespace option {
|
||||
|
||||
/// Holder of axis options.
|
||||
template <unsigned Bits>
|
||||
struct bitset : std::integral_constant<unsigned, Bits> {
|
||||
/// Returns true if all option flags in the argument are set and false otherwise.
|
||||
template <unsigned B>
|
||||
static constexpr auto test(bitset<B>) {
|
||||
return std::integral_constant<bool, static_cast<bool>(Bits & B)>{};
|
||||
}
|
||||
};
|
||||
|
||||
/// Set union of the axis option arguments.
|
||||
template <unsigned B1, unsigned B2>
|
||||
constexpr auto operator|(bitset<B1>, bitset<B2>) {
|
||||
return bitset<(B1 | B2)>{};
|
||||
}
|
||||
|
||||
/// Set intersection of the option arguments.
|
||||
template <unsigned B1, unsigned B2>
|
||||
constexpr auto operator&(bitset<B1>, bitset<B2>) {
|
||||
return bitset<(B1 & B2)>{};
|
||||
}
|
||||
|
||||
/// Set difference of the option arguments.
|
||||
template <unsigned B1, unsigned B2>
|
||||
constexpr auto operator-(bitset<B1>, bitset<B2>) {
|
||||
return bitset<(B1 & ~B2)>{};
|
||||
}
|
||||
|
||||
/**
|
||||
Single option flag.
|
||||
|
||||
@tparam Pos position of the bit in the set.
|
||||
*/
|
||||
template <unsigned Pos>
|
||||
struct bit : bitset<(1 << Pos)> {};
|
||||
|
||||
/// All options off.
|
||||
using none_t = bitset<0>;
|
||||
constexpr none_t none{}; ///< Instance of `none_t`.
|
||||
/// Axis has an underflow bin. Mutually exclusive with `circular`.
|
||||
using underflow_t = bit<0>;
|
||||
constexpr underflow_t underflow{}; ///< Instance of `underflow_t`.
|
||||
/// Axis has overflow bin.
|
||||
using overflow_t = bit<1>;
|
||||
constexpr overflow_t overflow{}; ///< Instance of `overflow_t`.
|
||||
/// Axis is circular. Mutually exclusive with `growth` and `underflow`.
|
||||
using circular_t = bit<2>;
|
||||
constexpr circular_t circular{}; ///< Instance of `circular_t`.
|
||||
/// Axis can grow. Mutually exclusive with `circular`.
|
||||
using growth_t = bit<3>;
|
||||
constexpr growth_t growth{}; ///< Instance of `growth_t`.
|
||||
|
||||
} // namespace option
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
193
macx64/include/boost/histogram/axis/ostream.hpp
Normal file
193
macx64/include/boost/histogram/axis/ostream.hpp
Normal file
@@ -0,0 +1,193 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// String representations here evaluate correctly in Python.
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_OSTREAM_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_OSTREAM_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/typeinfo.hpp>
|
||||
#include <boost/histogram/axis/regular.hpp>
|
||||
#include <boost/histogram/detail/cat.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <iomanip>
|
||||
#include <iosfwd>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
namespace detail {
|
||||
inline const char* axis_suffix(const axis::transform::id&) { return ""; }
|
||||
inline const char* axis_suffix(const axis::transform::log&) { return "_log"; }
|
||||
inline const char* axis_suffix(const axis::transform::sqrt&) { return "_sqrt"; }
|
||||
inline const char* axis_suffix(const axis::transform::pow&) { return "_pow"; }
|
||||
|
||||
template <class OStream, class T>
|
||||
void stream_metadata(OStream& os, const T& t) {
|
||||
detail::static_if<detail::is_streamable<T>>(
|
||||
[&os](const auto& t) {
|
||||
std::ostringstream oss;
|
||||
oss << t;
|
||||
if (!oss.str().empty()) { os << ", metadata=" << std::quoted(oss.str()); }
|
||||
},
|
||||
[&os](const auto&) {
|
||||
os << ", metadata=" << boost::core::demangled_name(BOOST_CORE_TYPEID(T));
|
||||
},
|
||||
t);
|
||||
}
|
||||
|
||||
template <class OStream>
|
||||
void stream_options(OStream& os, const unsigned bits) {
|
||||
os << ", options=";
|
||||
bool first = true;
|
||||
|
||||
#define BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(x) \
|
||||
if (bits & axis::option::x) { \
|
||||
if (first) \
|
||||
first = false; \
|
||||
else { \
|
||||
os << " | "; \
|
||||
} \
|
||||
os << #x; \
|
||||
}
|
||||
|
||||
BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(underflow);
|
||||
BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(overflow);
|
||||
BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(circular);
|
||||
BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(growth);
|
||||
|
||||
#undef BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM
|
||||
|
||||
if (first) os << "none";
|
||||
}
|
||||
|
||||
template <class OStream, class T>
|
||||
void stream_transform(OStream&, const T&) {}
|
||||
|
||||
template <class OStream>
|
||||
void stream_transform(OStream& os, const axis::transform::pow& t) {
|
||||
os << ", power=" << t.power;
|
||||
}
|
||||
|
||||
template <class OStream, class T>
|
||||
void stream_value(OStream& os, const T& t) {
|
||||
os << t;
|
||||
}
|
||||
|
||||
template <class OStream, class... Ts>
|
||||
void stream_value(OStream& os, const std::basic_string<Ts...>& t) {
|
||||
os << std::quoted(t);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
namespace axis {
|
||||
|
||||
template <class T>
|
||||
class polymorphic_bin;
|
||||
|
||||
template <class... Ts>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const null_type&) {
|
||||
return os; // do nothing
|
||||
}
|
||||
|
||||
template <class... Ts, class U>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const interval_view<U>& i) {
|
||||
os << "[" << i.lower() << ", " << i.upper() << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class... Ts, class U>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const polymorphic_bin<U>& i) {
|
||||
if (i.is_discrete())
|
||||
os << static_cast<double>(i);
|
||||
else
|
||||
os << "[" << i.lower() << ", " << i.upper() << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const regular<Us...>& a) {
|
||||
os << "regular" << detail::axis_suffix(a.transform()) << "(" << a.size() << ", "
|
||||
<< a.value(0) << ", " << a.value(a.size());
|
||||
detail::stream_metadata(os, a.metadata());
|
||||
detail::stream_options(os, a.options());
|
||||
detail::stream_transform(os, a.transform());
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const integer<Us...>& a) {
|
||||
os << "integer(" << a.value(0) << ", " << a.value(a.size());
|
||||
detail::stream_metadata(os, a.metadata());
|
||||
detail::stream_options(os, a.options());
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const variable<Us...>& a) {
|
||||
os << "variable(" << a.value(0);
|
||||
for (index_type i = 1, n = a.size(); i <= n; ++i) { os << ", " << a.value(i); }
|
||||
detail::stream_metadata(os, a.metadata());
|
||||
detail::stream_options(os, a.options());
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const category<Us...>& a) {
|
||||
os << "category(";
|
||||
for (index_type i = 0, n = a.size(); i < n; ++i) {
|
||||
detail::stream_value(os, a.value(i));
|
||||
os << (i == (a.size() - 1) ? "" : ", ");
|
||||
}
|
||||
detail::stream_metadata(os, a.metadata());
|
||||
detail::stream_options(os, a.options());
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const variant<Us...>& v) {
|
||||
visit(
|
||||
[&os](const auto& x) {
|
||||
using A = detail::remove_cvref_t<decltype(x)>;
|
||||
detail::static_if<detail::is_streamable<A>>(
|
||||
[&os](const auto& x) { os << x; },
|
||||
[](const auto&) {
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(
|
||||
detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(A)),
|
||||
" is not streamable")));
|
||||
},
|
||||
x);
|
||||
},
|
||||
v);
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
#endif
|
||||
88
macx64/include/boost/histogram/axis/polymorphic_bin.hpp
Normal file
88
macx64/include/boost/histogram/axis/polymorphic_bin.hpp
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
|
||||
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
/**
|
||||
Holds the bin data of a axis::variant.
|
||||
|
||||
The interface is a superset of the `value_bin_view` and `interval_bin_view`
|
||||
classes. The methods value() and lower() return the same number. For a value bin,
|
||||
upper() and lower() and center() return the same number, width() returns zero.
|
||||
|
||||
This is not a view like interval_bin_view or value_bin_view for two reasons.
|
||||
- Sequential calls to lower() and upper() would have to each loop through
|
||||
the variant types. This is likely to be slower than filling all the data in
|
||||
one loop.
|
||||
- polymorphic_bin may be created from a temporary instance of axis::variant,
|
||||
like in the call histogram::axis(0). Storing a reference to the axis would
|
||||
result in a dangling reference. Rather than specialing the code to handle
|
||||
this, it seems easier to just use a value instead of a view here.
|
||||
*/
|
||||
template <typename RealType>
|
||||
class polymorphic_bin {
|
||||
using value_type = RealType;
|
||||
|
||||
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 <typename BinType>
|
||||
bool operator==(const BinType& rhs) const noexcept {
|
||||
return equal_impl(detail::has_method_lower<BinType>(), rhs);
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
bool operator!=(const BinType& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
/// Return true if bin is discrete.
|
||||
bool is_discrete() const noexcept { return lower_or_value_ == upper_; }
|
||||
|
||||
private:
|
||||
bool equal_impl(std::true_type, const polymorphic_bin& rhs) const noexcept {
|
||||
return lower_or_value_ == rhs.lower_or_value_ && upper_ == rhs.upper_;
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
bool equal_impl(std::true_type, const BinType& rhs) const noexcept {
|
||||
return lower() == rhs.lower() && upper() == rhs.upper();
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
bool equal_impl(std::false_type, const BinType& rhs) const noexcept {
|
||||
return is_discrete() && static_cast<value_type>(*this) == rhs;
|
||||
}
|
||||
|
||||
const value_type lower_or_value_, upper_;
|
||||
};
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
359
macx64/include/boost/histogram/axis/regular.hpp
Normal file
359
macx64/include/boost/histogram/axis/regular.hpp
Normal file
@@ -0,0 +1,359 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_REGULAR_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_REGULAR_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/axis/interval_view.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/compressed_pair.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
namespace transform {
|
||||
|
||||
/// Identity transform for equidistant bins.
|
||||
struct id {
|
||||
/// Pass-through.
|
||||
template <typename T>
|
||||
static T forward(T&& x) noexcept {
|
||||
return std::forward<T>(x);
|
||||
}
|
||||
|
||||
/// Pass-through.
|
||||
template <typename T>
|
||||
static T inverse(T&& x) noexcept {
|
||||
return std::forward<T>(x);
|
||||
}
|
||||
};
|
||||
|
||||
/// Log transform for equidistant bins in log-space.
|
||||
struct log {
|
||||
/// Returns log(x) of external value x.
|
||||
template <typename T>
|
||||
static T forward(T x) {
|
||||
return std::log(x);
|
||||
}
|
||||
|
||||
/// Returns exp(x) for internal value x.
|
||||
template <typename T>
|
||||
static T inverse(T x) {
|
||||
return std::exp(x);
|
||||
}
|
||||
};
|
||||
|
||||
/// Sqrt transform for equidistant bins in sqrt-space.
|
||||
struct sqrt {
|
||||
/// Returns sqrt(x) of external value x.
|
||||
template <typename T>
|
||||
static T forward(T x) {
|
||||
return std::sqrt(x);
|
||||
}
|
||||
|
||||
/// Returns x^2 of internal value x.
|
||||
template <typename T>
|
||||
static T inverse(T x) {
|
||||
return x * x;
|
||||
}
|
||||
};
|
||||
|
||||
/// Pow transform for equidistant bins in pow-space.
|
||||
struct pow {
|
||||
double power = 1; /**< power index */
|
||||
|
||||
/// Make transform with index p.
|
||||
explicit pow(double p) : power(p) {}
|
||||
pow() = default;
|
||||
|
||||
/// Returns pow(x, power) of external value x.
|
||||
template <typename T>
|
||||
auto forward(T x) const {
|
||||
return std::pow(x, power);
|
||||
}
|
||||
|
||||
/// Returns pow(x, 1/power) of external value x.
|
||||
template <typename T>
|
||||
auto inverse(T x) const {
|
||||
return std::pow(x, 1.0 / power);
|
||||
}
|
||||
|
||||
bool operator==(const pow& o) const noexcept { return power == o.power; }
|
||||
};
|
||||
|
||||
} // namespace transform
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
// Type envelope to mark value as step size
|
||||
template <typename T>
|
||||
struct step_type {
|
||||
T value;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
Helper function to mark argument as step size.
|
||||
*/
|
||||
template <typename T>
|
||||
auto step(T&& t) {
|
||||
return step_type<T&&>{std::forward<T>(t)};
|
||||
}
|
||||
|
||||
/**
|
||||
Axis for equidistant intervals on the real line.
|
||||
|
||||
The most common binning strategy. Very fast. Binning is a O(1) operation.
|
||||
|
||||
@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 (all values allowed).
|
||||
*/
|
||||
template <class Value, class Transform, class MetaData, class Options>
|
||||
class regular : public iterator_mixin<regular<Value, Transform, MetaData, Options>>,
|
||||
protected detail::replace_default<Transform, transform::id> {
|
||||
using value_type = Value;
|
||||
using transform_type = detail::replace_default<Transform, transform::id>;
|
||||
using metadata_type = detail::replace_default<MetaData, std::string>;
|
||||
using options_type =
|
||||
detail::replace_default<Options, decltype(option::underflow | option::overflow)>;
|
||||
|
||||
using unit_type = detail::get_unit_type<value_type>;
|
||||
using internal_value_type = detail::get_scale_type<value_type>;
|
||||
static_assert(std::is_floating_point<internal_value_type>::value,
|
||||
"variable axis requires floating point type");
|
||||
|
||||
public:
|
||||
constexpr regular() = default;
|
||||
|
||||
/** 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).
|
||||
*/
|
||||
regular(transform_type trans, unsigned n, value_type start, value_type stop,
|
||||
metadata_type meta = {})
|
||||
: transform_type(std::move(trans))
|
||||
, size_meta_(static_cast<index_type>(n), std::move(meta))
|
||||
, min_(this->forward(detail::get_scale(start)))
|
||||
, delta_(this->forward(detail::get_scale(stop)) - min_) {
|
||||
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"));
|
||||
if (delta_ == 0)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("range of axis is zero"));
|
||||
}
|
||||
|
||||
/** Construct n bins over real range [start, stop).
|
||||
*
|
||||
* @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).
|
||||
*/
|
||||
regular(unsigned n, value_type start, value_type stop, metadata_type meta = {})
|
||||
: regular({}, n, start, stop, std::move(meta)) {}
|
||||
|
||||
/** Construct bins with the given step size over real transformed range
|
||||
* [start, stop).
|
||||
*
|
||||
* @param trans transform instance to use.
|
||||
* @param step width of a single bin.
|
||||
* @param start low edge of first bin.
|
||||
* @param stop upper limit of high edge of last bin (see below).
|
||||
* @param meta description of the axis (optional).
|
||||
*
|
||||
* The axis computes the number of bins as n = abs(stop - start) / step,
|
||||
* rounded down. This means that stop is an upper limit to the actual value
|
||||
* (start + n * step).
|
||||
*/
|
||||
template <class T>
|
||||
regular(transform_type trans, const step_type<T>& step, value_type start,
|
||||
value_type stop, metadata_type meta = {})
|
||||
: regular(trans, static_cast<index_type>(std::abs(stop - start) / step.value),
|
||||
start,
|
||||
start + static_cast<index_type>(std::abs(stop - start) / step.value) *
|
||||
step.value,
|
||||
std::move(meta)) {}
|
||||
|
||||
/** Construct bins with the given step size over real range [start, stop).
|
||||
*
|
||||
* @param step width of a single bin.
|
||||
* @param start low edge of first bin.
|
||||
* @param stop upper limit of high edge of last bin (see below).
|
||||
* @param meta description of the axis (optional).
|
||||
*
|
||||
* The axis computes the number of bins as n = abs(stop - start) / step,
|
||||
* rounded down. This means that stop is an upper limit to the actual value
|
||||
* (start + n * step).
|
||||
*/
|
||||
template <class T>
|
||||
regular(const step_type<T>& step, value_type start, value_type stop,
|
||||
metadata_type meta = {})
|
||||
: regular({}, step, start, stop, std::move(meta)) {}
|
||||
|
||||
/// Constructor used by algorithm::reduce to shrink and rebin (not for users).
|
||||
regular(const regular& src, index_type begin, index_type end, unsigned merge)
|
||||
: regular(src.transform(), (end - begin) / merge, src.value(begin), src.value(end),
|
||||
src.metadata()) {
|
||||
BOOST_ASSERT((end - begin) % merge == 0);
|
||||
if (options_type::test(option::circular) && !(begin == 0 && end == src.size()))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("cannot shrink circular axis"));
|
||||
}
|
||||
|
||||
/// Return instance of the transform type.
|
||||
const transform_type& transform() const noexcept { return *this; }
|
||||
|
||||
/// Return index for value argument.
|
||||
index_type index(value_type x) const noexcept {
|
||||
// Runs in hot loop, please measure impact of changes
|
||||
auto z = (this->forward(x / unit_type{}) - min_) / delta_;
|
||||
if (options_type::test(option::circular)) {
|
||||
if (std::isfinite(z)) {
|
||||
z -= std::floor(z);
|
||||
return static_cast<index_type>(z * size());
|
||||
}
|
||||
} else {
|
||||
if (z < 1) {
|
||||
if (z >= 0)
|
||||
return static_cast<index_type>(z * size());
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return size(); // also returned if x is NaN
|
||||
}
|
||||
|
||||
/// Returns index and shift (if axis has grown) for the passed argument.
|
||||
auto update(value_type x) noexcept {
|
||||
BOOST_ASSERT(options_type::test(option::growth));
|
||||
const auto z = (this->forward(x / unit_type{}) - min_) / delta_;
|
||||
if (z < 1) { // don't use i here!
|
||||
if (z >= 0) {
|
||||
const auto i = static_cast<axis::index_type>(z * size());
|
||||
return std::make_pair(i, 0);
|
||||
}
|
||||
if (z != -std::numeric_limits<internal_value_type>::infinity()) {
|
||||
const auto stop = min_ + delta_;
|
||||
const auto i = static_cast<axis::index_type>(std::floor(z * size()));
|
||||
min_ += i * (delta_ / size());
|
||||
delta_ = stop - min_;
|
||||
size_meta_.first() -= i;
|
||||
return std::make_pair(0, -i);
|
||||
}
|
||||
// z is -infinity
|
||||
return std::make_pair(-1, 0);
|
||||
}
|
||||
// z either beyond range, infinite, or NaN
|
||||
if (z < std::numeric_limits<internal_value_type>::infinity()) {
|
||||
const auto i = static_cast<axis::index_type>(z * size());
|
||||
const auto n = i - size() + 1;
|
||||
delta_ /= size();
|
||||
delta_ *= size() + n;
|
||||
size_meta_.first() += n;
|
||||
return std::make_pair(i, -n);
|
||||
}
|
||||
// z either infinite or NaN
|
||||
return std::make_pair(size(), 0);
|
||||
}
|
||||
|
||||
/// Return value for fractional index argument.
|
||||
value_type value(real_index_type i) const noexcept {
|
||||
auto z = i / size();
|
||||
if (!options_type::test(option::circular) && z < 0.0)
|
||||
z = -std::numeric_limits<internal_value_type>::infinity() * delta_;
|
||||
else if (options_type::test(option::circular) || z <= 1.0)
|
||||
z = (1.0 - z) * min_ + z * (min_ + delta_);
|
||||
else {
|
||||
z = std::numeric_limits<internal_value_type>::infinity() * delta_;
|
||||
}
|
||||
return static_cast<value_type>(this->inverse(z) * unit_type());
|
||||
}
|
||||
|
||||
/// Return bin for index argument.
|
||||
decltype(auto) bin(index_type idx) const noexcept {
|
||||
return interval_view<regular>(*this, idx);
|
||||
}
|
||||
|
||||
/// Returns the number of bins, without over- or underflow.
|
||||
index_type size() const noexcept { return size_meta_.first(); }
|
||||
/// Returns the options.
|
||||
static constexpr unsigned options() noexcept { return options_type::value; }
|
||||
/// Returns reference to metadata.
|
||||
metadata_type& metadata() noexcept { return size_meta_.second(); }
|
||||
/// Returns reference to const metadata.
|
||||
const metadata_type& metadata() const noexcept { return size_meta_.second(); }
|
||||
|
||||
template <class V, class T, class M, class O>
|
||||
bool operator==(const regular<V, T, M, O>& o) const noexcept {
|
||||
return detail::relaxed_equal(transform(), o.transform()) && size() == o.size() &&
|
||||
detail::relaxed_equal(metadata(), o.metadata()) && min_ == o.min_ &&
|
||||
delta_ == o.delta_;
|
||||
}
|
||||
template <class V, class T, class M, class O>
|
||||
bool operator!=(const regular<V, T, M, O>& o) const noexcept {
|
||||
return !operator==(o);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
|
||||
private:
|
||||
detail::compressed_pair<index_type, metadata_type> size_meta_{0};
|
||||
internal_value_type min_{0}, delta_{1};
|
||||
|
||||
template <class V, class T, class M, class O>
|
||||
friend class regular;
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
|
||||
template <class T>
|
||||
regular(unsigned, T, T)->regular<detail::convert_integer<T, double>>;
|
||||
|
||||
template <class T>
|
||||
regular(unsigned, T, T, const char*)->regular<detail::convert_integer<T, double>>;
|
||||
|
||||
template <class T, class M>
|
||||
regular(unsigned, T, T, M)->regular<detail::convert_integer<T, double>, transform::id, M>;
|
||||
|
||||
template <class Tr, class T>
|
||||
regular(Tr, unsigned, T, T)->regular<detail::convert_integer<T, double>, Tr>;
|
||||
|
||||
template <class Tr, class T>
|
||||
regular(Tr, unsigned, T, T, const char*)->regular<detail::convert_integer<T, double>, Tr>;
|
||||
|
||||
template <class Tr, class T, class M>
|
||||
regular(Tr, unsigned, T, T, M)->regular<detail::convert_integer<T, double>, Tr, M>;
|
||||
|
||||
#endif
|
||||
|
||||
template <class Value = double, class MetaData = use_default, class Options = use_default>
|
||||
using circular = regular<Value, transform::id, MetaData,
|
||||
decltype(detail::replace_default<Options, option::overflow_t>{} |
|
||||
option::circular)>;
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
283
macx64/include/boost/histogram/axis/traits.hpp
Normal file
283
macx64/include/boost/histogram/axis/traits.hpp
Normal file
@@ -0,0 +1,283 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_TRAITS_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_TRAITS_HPP
|
||||
|
||||
#include <boost/core/typeinfo.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/cat.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
using static_options_impl = axis::option::bitset<T::options()>;
|
||||
|
||||
template <class FIntArg, class FDoubleArg, class T>
|
||||
decltype(auto) value_method_switch(FIntArg&& iarg, FDoubleArg&& darg, const T& t) {
|
||||
return static_if<has_method_value<T>>(
|
||||
[](FIntArg&& iarg, FDoubleArg&& darg, const auto& t) {
|
||||
using A = remove_cvref_t<decltype(t)>;
|
||||
return static_if<std::is_same<arg_type<decltype(&A::value), 0>, int>>(
|
||||
std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
|
||||
},
|
||||
[](FIntArg&&, FDoubleArg&&, const auto& t) -> double {
|
||||
using A = remove_cvref_t<decltype(t)>;
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(A)), " has no value method")));
|
||||
#ifndef _MSC_VER // msvc warns about unreachable return
|
||||
return double{};
|
||||
#endif
|
||||
},
|
||||
std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
|
||||
}
|
||||
|
||||
template <class R1, class R2, class FIntArg, class FDoubleArg, class T>
|
||||
R2 value_method_switch_with_return_type(FIntArg&& iarg, FDoubleArg&& darg, const T& t) {
|
||||
return static_if<has_method_value_with_convertible_return_type<T, R1>>(
|
||||
[](FIntArg&& iarg, FDoubleArg&& darg, const auto& t) -> R2 {
|
||||
using A = remove_cvref_t<decltype(t)>;
|
||||
return static_if<std::is_same<arg_type<decltype(&A::value), 0>, int>>(
|
||||
std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
|
||||
},
|
||||
[](FIntArg&&, FDoubleArg&&, const auto&) -> R2 {
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(
|
||||
detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(T)),
|
||||
" has no value method or return type is not convertible to ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(R1)))));
|
||||
#ifndef _MSC_VER // msvc warns about unreachable return
|
||||
// conjure a value out of thin air to satisfy syntactic requirement
|
||||
return *reinterpret_cast<R2*>(0);
|
||||
#endif
|
||||
},
|
||||
std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
namespace axis {
|
||||
namespace traits {
|
||||
|
||||
/** Returns reference to metadata of an axis.
|
||||
|
||||
If the expression x.metadata() for an axis instance `x` (maybe const) is valid, return
|
||||
the result. Otherwise, return a reference to a static instance of
|
||||
boost::histogram::axis::null_type.
|
||||
|
||||
@param axis any axis instance
|
||||
*/
|
||||
template <class Axis>
|
||||
decltype(auto) metadata(Axis&& axis) noexcept {
|
||||
return detail::static_if<
|
||||
detail::has_method_metadata<const detail::remove_cvref_t<Axis>>>(
|
||||
[](auto&& a) -> decltype(auto) { return a.metadata(); },
|
||||
[](auto &&) -> detail::copy_qualifiers<Axis, null_type> {
|
||||
static null_type m;
|
||||
return m;
|
||||
},
|
||||
std::forward<Axis>(axis));
|
||||
}
|
||||
|
||||
/** Generates static axis option type for axis type.
|
||||
|
||||
WARNING: Doxygen does not render the synopsis correctly. This is a templated using
|
||||
directive, which accepts axis type and returns boost::histogram::axis::option::bitset.
|
||||
|
||||
If Axis::options() is valid and constexpr, return the corresponding option type.
|
||||
Otherwise, return boost::histogram::axis::option::growth_t, if the axis has a method
|
||||
`update`, else return boost::histogram::axis::option::none_t.
|
||||
|
||||
@tparam Axis axis type
|
||||
*/
|
||||
template <class Axis>
|
||||
using static_options = detail::mp_eval_or<
|
||||
mp11::mp_if<detail::has_method_update<detail::remove_cvref_t<Axis>>, option::growth_t,
|
||||
option::none_t>,
|
||||
detail::static_options_impl, detail::remove_cvref_t<Axis>>;
|
||||
|
||||
/** Returns axis options as unsigned integer.
|
||||
|
||||
If axis.options() is valid, return the result. Otherwise, return
|
||||
boost::histogram::axis::traits::static_options<decltype(axis)>::value.
|
||||
|
||||
@param axis any axis instance
|
||||
*/
|
||||
template <class Axis>
|
||||
constexpr unsigned options(const Axis& axis) noexcept {
|
||||
// cannot reuse static_options here, because this should also work for axis::variant
|
||||
return detail::static_if<detail::has_method_options<Axis>>(
|
||||
[](const auto& a) { return a.options(); },
|
||||
[](const auto&) { return static_options<Axis>::value; }, axis);
|
||||
}
|
||||
|
||||
/** Returns axis size plus any extra bins for under- and overflow.
|
||||
|
||||
@param axis any axis instance
|
||||
*/
|
||||
template <class Axis>
|
||||
constexpr index_type extent(const Axis& axis) noexcept {
|
||||
const auto opt = options(axis);
|
||||
return axis.size() + (opt & option::underflow ? 1 : 0) +
|
||||
(opt & option::overflow ? 1 : 0);
|
||||
}
|
||||
|
||||
/** Returns axis value for index.
|
||||
|
||||
If the axis has no `value` method, throw std::runtime_error. If the method exists and
|
||||
accepts a floating point index, pass the index and return the result. If the method
|
||||
exists but accepts only integer indices, cast the floating point index to int, pass this
|
||||
index and return the result.
|
||||
|
||||
@param axis any axis instance
|
||||
@param index floating point axis index
|
||||
*/
|
||||
template <class Axis>
|
||||
decltype(auto) value(const Axis& axis, real_index_type index) {
|
||||
return detail::value_method_switch(
|
||||
[index](const auto& a) { return a.value(static_cast<int>(index)); },
|
||||
[index](const auto& a) { return a.value(index); }, axis);
|
||||
}
|
||||
|
||||
/** Returns axis value for index if it is convertible to target type or throws.
|
||||
|
||||
Like boost::histogram::axis::traits::value, but converts the result into the requested
|
||||
return type. If the conversion is not possible, throws std::runtime_error.
|
||||
|
||||
@tparam Result requested return type
|
||||
@tparam Axis axis type
|
||||
@param axis any axis instance
|
||||
@param index floating point axis index
|
||||
*/
|
||||
template <class Result, class Axis>
|
||||
Result value_as(const Axis& axis, real_index_type index) {
|
||||
return detail::value_method_switch_with_return_type<Result, Result>(
|
||||
[index](const auto& a) {
|
||||
return static_cast<Result>(a.value(static_cast<int>(index)));
|
||||
},
|
||||
[index](const auto& a) { return static_cast<Result>(a.value(index)); }, axis);
|
||||
}
|
||||
|
||||
/** Returns axis index for value.
|
||||
|
||||
Throws std::invalid_argument if the value argument is not implicitly convertible.
|
||||
|
||||
@param axis any axis instance
|
||||
@param value argument to be passed to `index` method
|
||||
*/
|
||||
template <class Axis, class U>
|
||||
auto index(const Axis& axis, const U& value) {
|
||||
using V = detail::arg_type<decltype(&Axis::index)>;
|
||||
return detail::static_if<std::is_convertible<U, V>>(
|
||||
[&value](const auto& axis) {
|
||||
using A = detail::remove_cvref_t<decltype(axis)>;
|
||||
using V2 = detail::arg_type<decltype(&A::index)>;
|
||||
return axis.index(static_cast<V2>(value));
|
||||
},
|
||||
[](const Axis&) -> index_type {
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument(
|
||||
detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(Axis)),
|
||||
": cannot convert argument of type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(U)), " to ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(V)))));
|
||||
#ifndef _MSC_VER // msvc warns about unreachable return
|
||||
return index_type{};
|
||||
#endif
|
||||
},
|
||||
axis);
|
||||
}
|
||||
|
||||
/// @copydoc index(const Axis&, const U& value)
|
||||
template <class... Ts, class U>
|
||||
auto index(const variant<Ts...>& axis, const U& value) {
|
||||
return axis.index(value);
|
||||
}
|
||||
|
||||
/** Returns pair of axis index and shift for the value argument.
|
||||
|
||||
Throws `std::invalid_argument` if the value argument is not implicitly convertible to
|
||||
the argument expected by the `index` method. If the result of
|
||||
boost::histogram::axis::traits::static_options<decltype(axis)> has the growth flag set,
|
||||
call `update` method with the argument and return the result. Otherwise, call `index`
|
||||
and return the pair of the result and a zero shift.
|
||||
|
||||
@param axis any axis instance
|
||||
@param value argument to be passed to `update` or `index` method
|
||||
*/
|
||||
template <class Axis, class U>
|
||||
std::pair<int, int> update(Axis& axis, const U& value) {
|
||||
using V = detail::arg_type<decltype(&Axis::index)>;
|
||||
return detail::static_if<std::is_convertible<U, V>>(
|
||||
[&value](auto& a) {
|
||||
using A = detail::remove_cvref_t<decltype(a)>;
|
||||
return detail::static_if_c<static_options<A>::test(option::growth)>(
|
||||
[&value](auto& a) { return a.update(value); },
|
||||
[&value](auto& a) { return std::make_pair(a.index(value), 0); }, a);
|
||||
},
|
||||
[](Axis&) -> std::pair<index_type, index_type> {
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument(
|
||||
detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(Axis)),
|
||||
": cannot convert argument of type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(U)), " to ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(V)))));
|
||||
#ifndef _MSC_VER // msvc warns about unreachable return
|
||||
return std::make_pair(index_type{}, index_type{});
|
||||
#endif
|
||||
},
|
||||
axis);
|
||||
}
|
||||
|
||||
/// @copydoc update(Axis& axis, const U& value)
|
||||
template <class... Ts, class U>
|
||||
auto update(variant<Ts...>& axis, const U& value) {
|
||||
return axis.update(value);
|
||||
}
|
||||
|
||||
/** Returns bin width at axis index.
|
||||
|
||||
If the axis has no `value` method, throw std::runtime_error. If the method exists and
|
||||
accepts a floating point index, return the result of `axis.value(index + 1) -
|
||||
axis.value(index)`. If the method exists but accepts only integer indices, return 0.
|
||||
|
||||
@param axis any axis instance
|
||||
@param index bin index
|
||||
*/
|
||||
template <class Axis>
|
||||
decltype(auto) width(const Axis& axis, index_type index) {
|
||||
return detail::value_method_switch(
|
||||
[](const auto&) { return 0; },
|
||||
[index](const auto& a) { return a.value(index + 1) - a.value(index); }, axis);
|
||||
}
|
||||
|
||||
/** Returns bin width at axis index.
|
||||
|
||||
Like boost::histogram::axis::traits::width, but converts the result into the requested
|
||||
return type. If the conversion is not possible, throw std::runtime_error.
|
||||
|
||||
@param axis any axis instance
|
||||
@param index bin index
|
||||
*/
|
||||
template <class Result, class Axis>
|
||||
Result width_as(const Axis& axis, index_type index) {
|
||||
return detail::value_method_switch_with_return_type<Result, Result>(
|
||||
[](const auto&) { return Result{}; },
|
||||
[index](const auto& a) {
|
||||
return static_cast<Result>(a.value(index + 1) - a.value(index));
|
||||
},
|
||||
axis);
|
||||
}
|
||||
|
||||
} // namespace traits
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
242
macx64/include/boost/histogram/axis/variable.hpp
Normal file
242
macx64/include/boost/histogram/axis/variable.hpp
Normal file
@@ -0,0 +1,242 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_VARIABLE_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_VARIABLE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/axis/interval_view.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/compressed_pair.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
/**
|
||||
Axis for non-equidistant bins on the real line.
|
||||
|
||||
Binning is a O(log(N)) operation. If speed matters and the problem domain
|
||||
allows it, prefer a regular axis, possibly with a transform.
|
||||
|
||||
@tparam Value input value type, must be floating point.
|
||||
@tparam MetaData type to store meta data.
|
||||
@tparam Options see boost::histogram::axis::option (all values allowed).
|
||||
@tparam Allocator allocator to use for dynamic memory management.
|
||||
*/
|
||||
template <class Value, class MetaData, class Options, class Allocator>
|
||||
class variable : public iterator_mixin<variable<Value, MetaData, Options, Allocator>> {
|
||||
static_assert(std::is_floating_point<Value>::value,
|
||||
"variable axis requires floating point type");
|
||||
|
||||
using value_type = Value;
|
||||
using metadata_type = detail::replace_default<MetaData, std::string>;
|
||||
using options_type =
|
||||
detail::replace_default<Options, decltype(option::underflow | option::overflow)>;
|
||||
using allocator_type = Allocator;
|
||||
using vec_type = std::vector<Value, allocator_type>;
|
||||
|
||||
public:
|
||||
explicit variable(allocator_type alloc = {}) : vec_meta_(std::move(alloc)) {}
|
||||
|
||||
/** Construct from iterator range of bin edges.
|
||||
*
|
||||
* \param begin begin of edge sequence.
|
||||
* \param end end of edge sequence.
|
||||
* \param meta description of the axis.
|
||||
* \param alloc allocator instance to use.
|
||||
*/
|
||||
template <class It, class = detail::requires_iterator<It>>
|
||||
variable(It begin, It end, metadata_type meta = {}, allocator_type alloc = {})
|
||||
: vec_meta_(vec_type(std::move(alloc)), std::move(meta)) {
|
||||
if (std::distance(begin, end) <= 1)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
|
||||
|
||||
auto& v = vec_meta_.first();
|
||||
v.reserve(std::distance(begin, end));
|
||||
v.emplace_back(*begin++);
|
||||
while (begin != end) {
|
||||
if (*begin <= v.back())
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("input sequence must be strictly ascending"));
|
||||
v.emplace_back(*begin++);
|
||||
}
|
||||
}
|
||||
|
||||
/** Construct variable axis from iterable range of bin edges.
|
||||
*
|
||||
* \param iterable iterable range of bin edges.
|
||||
* \param meta description of the axis.
|
||||
* \param alloc allocator instance to use.
|
||||
*/
|
||||
template <class U, class = detail::requires_iterable<U>>
|
||||
variable(const U& iterable, metadata_type meta = {}, allocator_type alloc = {})
|
||||
: variable(std::begin(iterable), std::end(iterable), std::move(meta),
|
||||
std::move(alloc)) {}
|
||||
|
||||
/** Construct variable axis from 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.
|
||||
*/
|
||||
template <class U>
|
||||
variable(std::initializer_list<U> list, metadata_type meta = {},
|
||||
allocator_type alloc = {})
|
||||
: variable(list.begin(), list.end(), std::move(meta), std::move(alloc)) {}
|
||||
|
||||
/// Constructor used by algorithm::reduce to shrink and rebin (not for users).
|
||||
variable(const variable& src, index_type begin, index_type end, unsigned merge)
|
||||
: vec_meta_(vec_type(src.get_allocator()), src.metadata()) {
|
||||
BOOST_ASSERT((end - begin) % merge == 0);
|
||||
if (options_type::test(option::circular) && !(begin == 0 && end == src.size()))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("cannot shrink circular axis"));
|
||||
auto& vec = vec_meta_.first();
|
||||
vec.reserve((end - begin) / merge);
|
||||
const auto beg = src.vec_meta_.first().begin();
|
||||
for (index_type i = begin; i <= end; i += merge) vec.emplace_back(*(beg + i));
|
||||
}
|
||||
|
||||
/// Return index for value argument.
|
||||
index_type index(value_type x) const noexcept {
|
||||
const auto& v = vec_meta_.first();
|
||||
if (options_type::test(option::circular)) {
|
||||
const auto a = v[0];
|
||||
const auto b = v[size()];
|
||||
x -= std::floor((x - a) / (b - a)) * (b - a);
|
||||
}
|
||||
return static_cast<index_type>(std::upper_bound(v.begin(), v.end(), x) - v.begin() -
|
||||
1);
|
||||
}
|
||||
|
||||
auto update(value_type x) noexcept {
|
||||
const auto i = index(x);
|
||||
if (std::isfinite(x)) {
|
||||
auto& vec = vec_meta_.first();
|
||||
if (0 <= i) {
|
||||
if (i < size()) return std::make_pair(i, 0);
|
||||
const auto d = value(size()) - value(size() - 0.5);
|
||||
x = std::nextafter(x, std::numeric_limits<value_type>::max());
|
||||
x = std::max(x, vec.back() + d);
|
||||
vec.push_back(x);
|
||||
return std::make_pair(i, -1);
|
||||
}
|
||||
const auto d = value(0.5) - value(0);
|
||||
x = std::min(x, value(0) - d);
|
||||
vec.insert(vec.begin(), x);
|
||||
return std::make_pair(0, -i);
|
||||
}
|
||||
return std::make_pair(x < 0 ? -1 : size(), 0);
|
||||
}
|
||||
|
||||
/// Return value for fractional index argument.
|
||||
value_type value(real_index_type i) const noexcept {
|
||||
const auto& v = vec_meta_.first();
|
||||
if (options_type::test(option::circular)) {
|
||||
auto shift = std::floor(i / size());
|
||||
i -= shift * size();
|
||||
double z;
|
||||
const auto k = static_cast<index_type>(std::modf(i, &z));
|
||||
const auto a = v[0];
|
||||
const auto b = v[size()];
|
||||
return (1.0 - z) * v[k] + z * v[k + 1] + shift * (b - a);
|
||||
}
|
||||
if (i < 0) return detail::lowest<value_type>();
|
||||
if (i == size()) return v.back();
|
||||
if (i > size()) return detail::highest<value_type>();
|
||||
const auto k = static_cast<index_type>(i); // precond: i >= 0
|
||||
const real_index_type z = i - k;
|
||||
return (1.0 - z) * v[k] + z * v[k + 1];
|
||||
}
|
||||
|
||||
/// Return bin for index argument.
|
||||
auto bin(index_type idx) const noexcept { return interval_view<variable>(*this, idx); }
|
||||
|
||||
/// Returns the number of bins, without over- or underflow.
|
||||
index_type size() const noexcept {
|
||||
return static_cast<index_type>(vec_meta_.first().size()) - 1;
|
||||
}
|
||||
/// Returns the options.
|
||||
static constexpr unsigned options() noexcept { return options_type::value; }
|
||||
/// Returns reference to metadata.
|
||||
metadata_type& metadata() noexcept { return vec_meta_.second(); }
|
||||
/// Returns reference to const metadata.
|
||||
const metadata_type& metadata() const noexcept { return vec_meta_.second(); }
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
bool operator==(const variable<V, M, O, A>& o) const noexcept {
|
||||
const auto& a = vec_meta_.first();
|
||||
const auto& b = o.vec_meta_.first();
|
||||
return std::equal(a.begin(), a.end(), b.begin(), b.end()) &&
|
||||
detail::relaxed_equal(metadata(), o.metadata());
|
||||
}
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
bool operator!=(const variable<V, M, O, A>& o) const noexcept {
|
||||
return !operator==(o);
|
||||
}
|
||||
|
||||
/// Return allocator instance.
|
||||
auto get_allocator() const { return vec_meta_.first().get_allocator(); }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
|
||||
private:
|
||||
detail::compressed_pair<vec_type, metadata_type> vec_meta_;
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
friend class variable;
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
|
||||
template <class U, class T = detail::convert_integer<U, double>>
|
||||
variable(std::initializer_list<U>)->variable<T>;
|
||||
|
||||
template <class U, class T = detail::convert_integer<U, double>>
|
||||
variable(std::initializer_list<U>, const char*)->variable<T>;
|
||||
|
||||
template <class U, class M, class T = detail::convert_integer<U, double>>
|
||||
variable(std::initializer_list<U>, M)->variable<T, M>;
|
||||
|
||||
template <
|
||||
class Iterable,
|
||||
class T = detail::convert_integer<
|
||||
detail::remove_cvref_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
|
||||
variable(Iterable)->variable<T>;
|
||||
|
||||
template <
|
||||
class Iterable,
|
||||
class T = detail::convert_integer<
|
||||
detail::remove_cvref_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
|
||||
variable(Iterable, const char*)->variable<T>;
|
||||
|
||||
template <
|
||||
class Iterable, class M,
|
||||
class T = detail::convert_integer<
|
||||
detail::remove_cvref_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
|
||||
variable(Iterable, M)->variable<T, M>;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
299
macx64/include/boost/histogram/axis/variant.hpp
Normal file
299
macx64/include/boost/histogram/axis/variant.hpp
Normal file
@@ -0,0 +1,299 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_VARIANT_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_VARIANT_HPP
|
||||
|
||||
#include <boost/core/typeinfo.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/polymorphic_bin.hpp>
|
||||
#include <boost/histogram/axis/traits.hpp>
|
||||
#include <boost/histogram/detail/cat.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/bind.hpp>
|
||||
#include <boost/mp11/function.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/get.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant.hpp>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
template <class T, class... Us>
|
||||
T* get_if(variant<Us...>* v);
|
||||
|
||||
template <class T, class... Us>
|
||||
const T* get_if(const variant<Us...>* v);
|
||||
|
||||
/// Polymorphic axis type
|
||||
template <class... Ts>
|
||||
class variant : public iterator_mixin<variant<Ts...>> {
|
||||
using impl_type = boost::variant<Ts...>;
|
||||
using raw_types = mp11::mp_transform<detail::remove_cvref_t, impl_type>;
|
||||
|
||||
template <class T>
|
||||
using is_bounded_type = mp11::mp_contains<raw_types, detail::remove_cvref_t<T>>;
|
||||
|
||||
template <typename T>
|
||||
using requires_bounded_type = std::enable_if_t<is_bounded_type<T>::value>;
|
||||
|
||||
// maybe metadata_type or const metadata_type, if bounded type is const
|
||||
using metadata_type = std::remove_reference_t<decltype(
|
||||
traits::metadata(std::declval<mp11::mp_first<impl_type>>()))>;
|
||||
|
||||
public:
|
||||
// cannot import ctors with using directive, it breaks gcc and msvc
|
||||
variant() = default;
|
||||
variant(const variant&) = default;
|
||||
variant& operator=(const variant&) = default;
|
||||
variant(variant&&) = default;
|
||||
variant& operator=(variant&&) = default;
|
||||
|
||||
template <typename T, typename = requires_bounded_type<T>>
|
||||
variant(T&& t) : impl(std::forward<T>(t)) {}
|
||||
|
||||
template <typename T, typename = requires_bounded_type<T>>
|
||||
variant& operator=(T&& t) {
|
||||
impl = std::forward<T>(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class... Us>
|
||||
variant(const variant<Us...>& u) {
|
||||
this->operator=(u);
|
||||
}
|
||||
|
||||
template <class... Us>
|
||||
variant& operator=(const variant<Us...>& u) {
|
||||
visit(
|
||||
[this](const auto& u) {
|
||||
using U = detail::remove_cvref_t<decltype(u)>;
|
||||
detail::static_if<is_bounded_type<U>>(
|
||||
[this](const auto& u) { this->operator=(u); },
|
||||
[](const auto&) {
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(U)),
|
||||
" is not convertible to a bounded type of ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(variant)))));
|
||||
},
|
||||
u);
|
||||
},
|
||||
u);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Return size of axis.
|
||||
index_type size() const {
|
||||
return visit([](const auto& x) { return x.size(); }, *this);
|
||||
}
|
||||
|
||||
/// Return options of axis or option::none_t if axis has no options.
|
||||
unsigned 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& {
|
||||
using M = decltype(traits::metadata(a));
|
||||
return detail::static_if<std::is_same<M, const metadata_type&>>(
|
||||
[](const auto& a) -> const metadata_type& { return traits::metadata(a); },
|
||||
[](const auto&) -> const metadata_type& {
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
|
||||
"cannot return metadata of type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(M)),
|
||||
" through axis::variant interface which uses type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(metadata_type)),
|
||||
"; use boost::histogram::axis::get to obtain a reference "
|
||||
"of this axis type")));
|
||||
},
|
||||
a);
|
||||
},
|
||||
*this);
|
||||
}
|
||||
|
||||
/// Return reference to metadata or instance of null_type if axis has no
|
||||
/// metadata.
|
||||
metadata_type& metadata() {
|
||||
return visit(
|
||||
[](auto&& a) -> metadata_type& {
|
||||
using M = decltype(traits::metadata(a));
|
||||
return detail::static_if<std::is_same<M, metadata_type&>>(
|
||||
[](auto& a) -> metadata_type& { return traits::metadata(a); },
|
||||
[](auto&) -> metadata_type& {
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
|
||||
"cannot return metadata of type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(M)),
|
||||
" through axis::variant interface which uses type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(metadata_type)),
|
||||
"; use boost::histogram::axis::get to obtain a reference "
|
||||
"of this axis type")));
|
||||
},
|
||||
a);
|
||||
},
|
||||
*this);
|
||||
}
|
||||
|
||||
/// Return index for value argument.
|
||||
/// Throws std::invalid_argument if axis has incompatible call signature.
|
||||
template <class U>
|
||||
index_type index(const U& u) const {
|
||||
return visit([&u](const auto& a) { return traits::index(a, u); }, *this);
|
||||
}
|
||||
|
||||
/// 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<double>(a, idx); },
|
||||
*this);
|
||||
}
|
||||
|
||||
/// 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 bin(index_type idx) const {
|
||||
return visit(
|
||||
[idx](const auto& a) {
|
||||
return detail::value_method_switch_with_return_type<double,
|
||||
polymorphic_bin<double>>(
|
||||
[idx](const auto& a) { // axis is discrete
|
||||
const auto x = a.value(idx);
|
||||
return polymorphic_bin<double>(x, x);
|
||||
},
|
||||
[idx](const auto& a) { // axis is continuous
|
||||
return polymorphic_bin<double>(a.value(idx), a.value(idx + 1));
|
||||
},
|
||||
a);
|
||||
},
|
||||
*this);
|
||||
}
|
||||
|
||||
template <class... Us>
|
||||
bool operator==(const variant<Us...>& u) const {
|
||||
return visit([&u](const auto& x) { return u == x; }, *this);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator==(const T& t) const {
|
||||
// boost::variant::operator==(T) implemented only to fail, cannot use it
|
||||
auto tp = get_if<T>(this);
|
||||
return tp && detail::relaxed_equal(*tp, t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator!=(const T& t) const {
|
||||
return !operator==(t);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned);
|
||||
|
||||
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);
|
||||
|
||||
template <class T, class... Us>
|
||||
friend const T& get(const variant<Us...>& v);
|
||||
|
||||
template <class T, class... Us>
|
||||
friend T&& get(variant<Us...>&& v);
|
||||
|
||||
template <class T, class... Us>
|
||||
friend T* get_if(variant<Us...>* v);
|
||||
|
||||
template <class T, class... Us>
|
||||
friend const T* get_if(const variant<Us...>* v);
|
||||
|
||||
private:
|
||||
boost::variant<Ts...> impl;
|
||||
};
|
||||
|
||||
/// Apply visitor to variant.
|
||||
template <class Visitor, class Variant>
|
||||
auto visit(Visitor&& vis, Variant&& var)
|
||||
-> detail::visitor_return_type<Visitor, Variant> {
|
||||
return boost::apply_visitor(std::forward<Visitor>(vis), var.impl);
|
||||
}
|
||||
|
||||
/// Return lvalue reference to T, throws unspecified exception if type does not
|
||||
/// match.
|
||||
template <class T, class... Us>
|
||||
T& get(variant<Us...>& v) {
|
||||
return boost::get<T>(v.impl);
|
||||
}
|
||||
|
||||
/// Return rvalue reference to T, throws unspecified exception if type does not
|
||||
/// match.
|
||||
template <class T, class... Us>
|
||||
T&& get(variant<Us...>&& v) {
|
||||
return boost::get<T>(std::move(v.impl));
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
return boost::get<T>(v.impl);
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
return boost::relaxed_get<T>(&(v->impl));
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
return boost::relaxed_get<T>(&(v->impl));
|
||||
}
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
// pass-through version of get for generic programming
|
||||
template <class T, class U>
|
||||
decltype(auto) get(U&& u) {
|
||||
return static_cast<detail::copy_qualifiers<U, T>>(u);
|
||||
}
|
||||
|
||||
// pass-through version of get_if for generic programming
|
||||
template <class T, class U>
|
||||
T* get_if(U* u) {
|
||||
return std::is_same<T, detail::remove_cvref_t<U>>::value ? reinterpret_cast<T*>(u)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
// pass-through version of get_if for generic programming
|
||||
template <class T, class U>
|
||||
const T* get_if(const U* u) {
|
||||
return std::is_same<T, detail::remove_cvref_t<U>>::value ? reinterpret_cast<const T*>(u)
|
||||
: nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
16
macx64/include/boost/histogram/detail/attribute.hpp
Normal file
16
macx64/include/boost/histogram/detail/attribute.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_ATTRIBUTE_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_ATTRIBUTE_HPP
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#define BOOST_HISTOGRAM_DETAIL_NODISCARD [[nodiscard]]
|
||||
#else
|
||||
#define BOOST_HISTOGRAM_DETAIL_NODISCARD
|
||||
#endif
|
||||
|
||||
#endif
|
||||
176
macx64/include/boost/histogram/detail/axes.hpp
Normal file
176
macx64/include/boost/histogram/detail/axes.hpp
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_AXES_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_AXES_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/axis/traits.hpp>
|
||||
#include <boost/histogram/axis/variant.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/mp11/tuple.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <unsigned N, class... Ts>
|
||||
decltype(auto) axis_get(std::tuple<Ts...>& axes) {
|
||||
return std::get<N>(axes);
|
||||
}
|
||||
|
||||
template <unsigned N, class... Ts>
|
||||
decltype(auto) axis_get(const std::tuple<Ts...>& axes) {
|
||||
return std::get<N>(axes);
|
||||
}
|
||||
|
||||
template <unsigned N, class T>
|
||||
decltype(auto) axis_get(T& axes) {
|
||||
return axes[N];
|
||||
}
|
||||
|
||||
template <unsigned N, class T>
|
||||
decltype(auto) axis_get(const T& axes) {
|
||||
return axes[N];
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
decltype(auto) axis_get(std::tuple<Ts...>& axes, unsigned i) {
|
||||
return mp11::mp_with_index<sizeof...(Ts)>(
|
||||
i, [&](auto I) { return axis::variant<Ts&...>(std::get<I>(axes)); });
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
decltype(auto) axis_get(const std::tuple<Ts...>& axes, unsigned i) {
|
||||
return mp11::mp_with_index<sizeof...(Ts)>(
|
||||
i, [&](auto I) { return axis::variant<const Ts&...>(std::get<I>(axes)); });
|
||||
}
|
||||
|
||||
template <class T>
|
||||
decltype(auto) axis_get(T& axes, unsigned i) {
|
||||
return axes.at(i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
decltype(auto) axis_get(const T& axes, unsigned i) {
|
||||
return axes.at(i);
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
bool axes_equal(const std::tuple<Ts...>& ts, const std::tuple<Us...>& us) {
|
||||
return static_if<std::is_same<mp11::mp_list<Ts...>, mp11::mp_list<Us...>>>(
|
||||
[](const auto& ts, const auto& us) {
|
||||
using N = mp11::mp_size<remove_cvref_t<decltype(ts)>>;
|
||||
bool equal = true;
|
||||
mp11::mp_for_each<mp11::mp_iota<N>>(
|
||||
[&](auto I) { equal &= relaxed_equal(std::get<I>(ts), std::get<I>(us)); });
|
||||
return equal;
|
||||
},
|
||||
[](const auto&, const auto&) { return false; }, ts, us);
|
||||
}
|
||||
|
||||
template <class... Ts, class U>
|
||||
bool axes_equal(const std::tuple<Ts...>& t, const U& u) {
|
||||
if (sizeof...(Ts) != u.size()) return false;
|
||||
bool equal = true;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Ts)>>(
|
||||
[&](auto I) { equal &= u[I] == std::get<I>(t); });
|
||||
return equal;
|
||||
}
|
||||
|
||||
template <class T, class... Us>
|
||||
bool axes_equal(const T& t, const std::tuple<Us...>& u) {
|
||||
return axes_equal(u, t);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool axes_equal(const T& t, const U& u) {
|
||||
if (t.size() != u.size()) return false;
|
||||
return std::equal(t.begin(), t.end(), u.begin());
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
void axes_assign(std::tuple<Ts...>& t, const std::tuple<Us...>& u) {
|
||||
static_if<std::is_same<mp11::mp_list<Ts...>, mp11::mp_list<Us...>>>(
|
||||
[](auto& a, const auto& b) { a = b; },
|
||||
[](auto&, const auto&) {
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("cannot assign axes, types do not match"));
|
||||
},
|
||||
t, u);
|
||||
}
|
||||
|
||||
template <class... Ts, class U>
|
||||
void axes_assign(std::tuple<Ts...>& t, const U& u) {
|
||||
mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Ts)>>([&](auto I) {
|
||||
using T = mp11::mp_at_c<std::tuple<Ts...>, I>;
|
||||
std::get<I>(t) = axis::get<T>(u[I]);
|
||||
});
|
||||
}
|
||||
|
||||
template <class T, class... Us>
|
||||
void axes_assign(T& t, const std::tuple<Us...>& u) {
|
||||
// resize instead of reserve, because t may not be empty and we want exact capacity
|
||||
t.resize(sizeof...(Us));
|
||||
mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Us)>>(
|
||||
[&](auto I) { t[I] = std::get<I>(u); });
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void axes_assign(T& t, const U& u) {
|
||||
t.assign(u.begin(), u.end());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void axis_index_is_valid(const T& axes, const unsigned N) {
|
||||
BOOST_ASSERT_MSG(N < get_size(axes), "index out of range");
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
void for_each_axis_impl(std::true_type, const T& axes, F&& f) {
|
||||
for (const auto& x : axes) { axis::visit(std::forward<F>(f), x); }
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
void for_each_axis_impl(std::false_type, const T& axes, F&& f) {
|
||||
for (const auto& x : axes) std::forward<F>(f)(x);
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
void for_each_axis(const T& axes, F&& f) {
|
||||
using U = mp11::mp_first<T>;
|
||||
for_each_axis_impl(is_axis_variant<U>(), axes, std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename F, typename... Ts>
|
||||
void for_each_axis(const std::tuple<Ts...>& axes, F&& f) {
|
||||
mp11::tuple_for_each(axes, std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t bincount(const T& axes) {
|
||||
std::size_t n = 1;
|
||||
for_each_axis(axes, [&n](const auto& a) {
|
||||
const auto old = n;
|
||||
const auto s = axis::traits::extent(a);
|
||||
n *= s;
|
||||
if (s > 0 && n < old) BOOST_THROW_EXCEPTION(std::overflow_error("bincount overflow"));
|
||||
});
|
||||
return n;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
34
macx64/include/boost/histogram/detail/cat.hpp
Normal file
34
macx64/include/boost/histogram/detail/cat.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_CAT_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_CAT_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <sstream>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
BOOST_ATTRIBUTE_UNUSED inline void cat_impl(std::ostringstream&) {}
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
void cat_impl(std::ostringstream& os, const T& t, const Ts&... ts) {
|
||||
os << t;
|
||||
cat_impl(os, ts...);
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
std::string cat(const Ts&... args) {
|
||||
std::ostringstream os;
|
||||
cat_impl(os, args...);
|
||||
return os.str();
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
78
macx64/include/boost/histogram/detail/common_type.hpp
Normal file
78
macx64/include/boost/histogram/detail/common_type.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_COMMON_TYPE_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_COMMON_TYPE_HPP
|
||||
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
// clang-format off
|
||||
template <class T, class U>
|
||||
using common_axes = mp11::mp_cond<
|
||||
is_tuple<T>, T,
|
||||
is_tuple<U>, U,
|
||||
is_sequence_of_axis<T>, T,
|
||||
is_sequence_of_axis<U>, U,
|
||||
std::true_type, T
|
||||
>;
|
||||
|
||||
template <class T, class U>
|
||||
using common_container = mp11::mp_cond<
|
||||
is_array_like<T>, T,
|
||||
is_array_like<U>, U,
|
||||
is_vector_like<T>, T,
|
||||
is_vector_like<U>, U,
|
||||
std::true_type, T
|
||||
>;
|
||||
// clang-format on
|
||||
|
||||
template <class T>
|
||||
using type_score = mp11::mp_size_t<((!std::is_pod<T>::value) * 1000 +
|
||||
std::is_floating_point<T>::value * 50 + sizeof(T))>;
|
||||
|
||||
template <class T, class U>
|
||||
struct common_storage_impl;
|
||||
|
||||
template <class T, class U>
|
||||
struct common_storage_impl<storage_adaptor<T>, storage_adaptor<U>> {
|
||||
using type =
|
||||
mp11::mp_if_c<(type_score<typename storage_adaptor<T>::value_type>::value >=
|
||||
type_score<typename storage_adaptor<U>::value_type>::value),
|
||||
storage_adaptor<T>, storage_adaptor<U>>;
|
||||
};
|
||||
|
||||
template <class T, class A>
|
||||
struct common_storage_impl<storage_adaptor<T>, unlimited_storage<A>> {
|
||||
using type =
|
||||
mp11::mp_if_c<(type_score<typename storage_adaptor<T>::value_type>::value >=
|
||||
type_score<typename unlimited_storage<A>::value_type>::value),
|
||||
storage_adaptor<T>, unlimited_storage<A>>;
|
||||
};
|
||||
|
||||
template <class C, class A>
|
||||
struct common_storage_impl<unlimited_storage<A>, storage_adaptor<C>>
|
||||
: common_storage_impl<storage_adaptor<C>, unlimited_storage<A>> {};
|
||||
|
||||
template <class A1, class A2>
|
||||
struct common_storage_impl<unlimited_storage<A1>, unlimited_storage<A2>> {
|
||||
using type = unlimited_storage<A1>;
|
||||
};
|
||||
|
||||
template <class A, class B>
|
||||
using common_storage = typename common_storage_impl<A, B>::type;
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
74
macx64/include/boost/histogram/detail/compressed_pair.hpp
Normal file
74
macx64/include/boost/histogram/detail/compressed_pair.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_COMPRESSED_PAIR_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_COMPRESSED_PAIR_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <typename T1, typename T2, bool B>
|
||||
class compressed_pair_impl;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
class compressed_pair_impl<T1, T2, true> : protected T2 {
|
||||
public:
|
||||
template <typename U1, typename U2>
|
||||
compressed_pair_impl(U1&& u1, U2&& u2)
|
||||
: T2(std::forward<U2>(u2)), first_(std::forward<U1>(u1)) {}
|
||||
template <typename U1>
|
||||
compressed_pair_impl(U1&& u1) : first_(std::forward<U1>(u1)) {}
|
||||
compressed_pair_impl() = default;
|
||||
|
||||
T1& first() { return first_; }
|
||||
T2& second() { return static_cast<T2&>(*this); }
|
||||
const T1& first() const { return first_; }
|
||||
const T2& second() const { return static_cast<const T2&>(*this); }
|
||||
|
||||
private:
|
||||
T1 first_;
|
||||
};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
class compressed_pair_impl<T1, T2, false> {
|
||||
public:
|
||||
template <typename U1, typename U2>
|
||||
compressed_pair_impl(U1&& u1, U2&& u2)
|
||||
: first_(std::forward<U1>(u1)), second_(std::forward<U2>(u2)) {}
|
||||
template <typename U1>
|
||||
compressed_pair_impl(U1&& u1) : first_(std::forward<U1>(u1)) {}
|
||||
compressed_pair_impl() = default;
|
||||
|
||||
T1& first() { return first_; }
|
||||
T2& second() { return second_; }
|
||||
const T1& first() const { return first_; }
|
||||
const T2& second() const { return second_; }
|
||||
|
||||
private:
|
||||
T1 first_;
|
||||
T2 second_;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
void swap(compressed_pair_impl<Ts...>& a, compressed_pair_impl<Ts...>& b) {
|
||||
using std::swap;
|
||||
swap(a.first(), b.first());
|
||||
swap(a.second(), b.second());
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
using compressed_pair =
|
||||
compressed_pair_impl<T1, T2, (!std::is_final<T2>::value && std::is_empty<T2>::value)>;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
337
macx64/include/boost/histogram/detail/linearize.hpp
Normal file
337
macx64/include/boost/histogram/detail/linearize.hpp
Normal file
@@ -0,0 +1,337 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_LINEARIZE_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_LINEARIZE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/axis/traits.hpp>
|
||||
#include <boost/histogram/axis/variant.hpp>
|
||||
#include <boost/histogram/detail/axes.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/histogram/unsafe_access.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/mp11/function.hpp>
|
||||
#include <boost/mp11/integral.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/mp11/tuple.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
struct is_accumulator_set : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
using has_underflow =
|
||||
decltype(axis::traits::static_options<T>::test(axis::option::underflow));
|
||||
|
||||
template <class T>
|
||||
struct is_growing
|
||||
: decltype(axis::traits::static_options<T>::test(axis::option::growth)) {};
|
||||
|
||||
template <class... Ts>
|
||||
struct is_growing<std::tuple<Ts...>> : mp11::mp_or<is_growing<Ts>...> {};
|
||||
|
||||
template <class... Ts>
|
||||
struct is_growing<axis::variant<Ts...>> : mp11::mp_or<is_growing<Ts>...> {};
|
||||
|
||||
template <class T>
|
||||
using has_growing_axis =
|
||||
mp11::mp_if<is_vector_like<T>, is_growing<mp11::mp_first<T>>, is_growing<T>>;
|
||||
|
||||
/// Index with an invalid state
|
||||
struct optional_index {
|
||||
std::size_t idx = 0;
|
||||
std::size_t stride = 1;
|
||||
operator bool() const { return stride > 0; }
|
||||
std::size_t operator*() const { return idx; }
|
||||
};
|
||||
|
||||
inline void linearize(optional_index& out, const axis::index_type extent,
|
||||
const axis::index_type j) noexcept {
|
||||
// j is internal index shifted by +1 if axis has underflow bin
|
||||
out.idx += j * out.stride;
|
||||
// set stride to 0, if j is invalid
|
||||
out.stride *= (0 <= j && j < extent) * extent;
|
||||
}
|
||||
|
||||
// for non-growing axis
|
||||
template <class Axis, class Value>
|
||||
void linearize_value(optional_index& o, const Axis& a, const Value& v) {
|
||||
using B = decltype(axis::traits::static_options<Axis>::test(axis::option::underflow));
|
||||
const auto j = axis::traits::index(a, v) + B::value;
|
||||
linearize(o, axis::traits::extent(a), j);
|
||||
}
|
||||
|
||||
// for variant that does not contain any growing axis
|
||||
template <class... Ts, class Value>
|
||||
void linearize_value(optional_index& o, const axis::variant<Ts...>& a, const Value& v) {
|
||||
axis::visit([&o, &v](const auto& a) { linearize_value(o, a, v); }, a);
|
||||
}
|
||||
|
||||
// for growing axis
|
||||
template <class Axis, class Value>
|
||||
void linearize_value(optional_index& o, axis::index_type& s, Axis& a, const Value& v) {
|
||||
axis::index_type j;
|
||||
std::tie(j, s) = axis::traits::update(a, v);
|
||||
j += has_underflow<Axis>::value;
|
||||
linearize(o, axis::traits::extent(a), j);
|
||||
}
|
||||
|
||||
// for variant which contains at least one growing axis
|
||||
template <class... Ts, class Value>
|
||||
void linearize_value(optional_index& o, axis::index_type& s, axis::variant<Ts...>& a,
|
||||
const Value& v) {
|
||||
axis::visit([&o, &s, &v](auto&& a) { linearize_value(o, s, a, v); }, a);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
void linearize_index(optional_index& out, const A& axis, const axis::index_type j) {
|
||||
// A may be axis or variant, cannot use static option detection here
|
||||
const auto opt = axis::traits::options(axis);
|
||||
const auto shift = opt & axis::option::underflow ? 1 : 0;
|
||||
const auto n = axis.size() + (opt & axis::option::overflow ? 1 : 0);
|
||||
linearize(out, n + shift, j + shift);
|
||||
}
|
||||
|
||||
template <class S, class A, class T>
|
||||
void maybe_replace_storage(S& storage, const A& axes, const T& shifts) {
|
||||
bool update_needed = false;
|
||||
auto sit = shifts;
|
||||
for_each_axis(axes, [&](const auto&) { update_needed |= (*sit++ != 0); });
|
||||
if (!update_needed) return;
|
||||
struct item {
|
||||
axis::index_type idx, old_extent;
|
||||
std::size_t new_stride;
|
||||
} data[buffer_size<A>::value];
|
||||
sit = shifts;
|
||||
auto dit = data;
|
||||
std::size_t s = 1;
|
||||
for_each_axis(axes, [&](const auto& a) {
|
||||
const auto n = axis::traits::extent(a);
|
||||
*dit++ = {0, n - std::abs(*sit++), s};
|
||||
s *= n;
|
||||
});
|
||||
auto new_storage = make_default(storage);
|
||||
new_storage.reset(detail::bincount(axes));
|
||||
const auto dlast = data + get_size(axes) - 1;
|
||||
for (const auto& x : storage) {
|
||||
auto ns = new_storage.begin();
|
||||
sit = shifts;
|
||||
dit = data;
|
||||
for_each_axis(axes, [&](const auto& a) {
|
||||
using opt = axis::traits::static_options<decltype(a)>;
|
||||
if (opt::test(axis::option::underflow)) {
|
||||
if (dit->idx == 0) {
|
||||
// axis has underflow and we are in the underflow bin:
|
||||
// keep storage pointer unchanged
|
||||
++dit;
|
||||
++sit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (opt::test(axis::option::overflow)) {
|
||||
if (dit->idx == dit->old_extent - 1) {
|
||||
// axis has overflow and we are in the overflow bin:
|
||||
// move storage pointer to corresponding overflow bin position
|
||||
ns += (axis::traits::extent(a) - 1) * dit->new_stride;
|
||||
++dit;
|
||||
++sit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// we are in a normal bin:
|
||||
// move storage pointer to index position, apply positive shifts
|
||||
ns += (dit->idx + std::max(*sit, 0)) * dit->new_stride;
|
||||
++dit;
|
||||
++sit;
|
||||
});
|
||||
// assign old value to new location
|
||||
*ns = x;
|
||||
// advance multi-dimensional index
|
||||
dit = data;
|
||||
++dit->idx;
|
||||
while (dit != dlast && dit->idx == dit->old_extent) {
|
||||
dit->idx = 0;
|
||||
++(++dit)->idx;
|
||||
}
|
||||
}
|
||||
storage = std::move(new_storage);
|
||||
}
|
||||
|
||||
// special case: if histogram::operator()(tuple(1, 2)) is called on 1d histogram
|
||||
// with axis that accepts 2d tuple, this should not fail
|
||||
// - solution is to forward tuples of size > 1 directly to axis for 1d
|
||||
// histograms
|
||||
// - has nice side-effect of making histogram::operator(1, 2) work as well
|
||||
// - cannot detect call signature of axis at compile-time in all configurations
|
||||
// (axis::variant provides generic call interface and hides concrete
|
||||
// interface), so we throw at runtime if incompatible argument is passed (e.g.
|
||||
// 3d tuple)
|
||||
// histogram has only non-growing axes
|
||||
template <unsigned I, unsigned N, class S, class T, class U>
|
||||
optional_index args_to_index(std::false_type, S&, const T& axes, const U& args) {
|
||||
optional_index idx;
|
||||
const auto rank = get_size(axes);
|
||||
if (rank == 1 && N > 1)
|
||||
linearize_value(idx, axis_get<0>(axes), tuple_slice<I, N>(args));
|
||||
else {
|
||||
if (rank != N)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("number of arguments != histogram rank"));
|
||||
constexpr unsigned M = buffer_size<remove_cvref_t<decltype(axes)>>::value;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<(N < M ? N : M)>>([&](auto J) {
|
||||
linearize_value(idx, axis_get<J>(axes), std::get<(J + I)>(args));
|
||||
});
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
// histogram has growing axes
|
||||
template <unsigned I, unsigned N, class S, class T, class U>
|
||||
optional_index args_to_index(std::true_type, S& storage, T& axes, const U& args) {
|
||||
optional_index idx;
|
||||
axis::index_type shifts[buffer_size<T>::value];
|
||||
const auto rank = get_size(axes);
|
||||
if (rank == 1 && N > 1)
|
||||
linearize_value(idx, shifts[0], axis_get<0>(axes), tuple_slice<I, N>(args));
|
||||
else {
|
||||
if (rank != N)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("number of arguments != histogram rank"));
|
||||
constexpr unsigned M = buffer_size<remove_cvref_t<decltype(axes)>>::value;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<(N < M ? N : M)>>([&](auto J) {
|
||||
linearize_value(idx, shifts[J], axis_get<J>(axes), std::get<(J + I)>(args));
|
||||
});
|
||||
}
|
||||
maybe_replace_storage(storage, axes, shifts);
|
||||
return idx;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
constexpr auto weight_sample_indices() {
|
||||
if (is_weight<U>::value) return std::make_pair(0, -1);
|
||||
if (is_sample<U>::value) return std::make_pair(-1, 0);
|
||||
return std::make_pair(-1, -1);
|
||||
}
|
||||
|
||||
template <typename U0, typename U1, typename... Us>
|
||||
constexpr auto weight_sample_indices() {
|
||||
using L = mp11::mp_list<U0, U1, Us...>;
|
||||
const int n = sizeof...(Us) + 1;
|
||||
if (is_weight<mp11::mp_at_c<L, 0>>::value) {
|
||||
if (is_sample<mp11::mp_at_c<L, 1>>::value) return std::make_pair(0, 1);
|
||||
if (is_sample<mp11::mp_at_c<L, n>>::value) return std::make_pair(0, n);
|
||||
return std::make_pair(0, -1);
|
||||
}
|
||||
if (is_sample<mp11::mp_at_c<L, 0>>::value) {
|
||||
if (is_weight<mp11::mp_at_c<L, 1>>::value) return std::make_pair(1, 0);
|
||||
if (is_weight<mp11::mp_at_c<L, n>>::value) return std::make_pair(n, 0);
|
||||
return std::make_pair(-1, 0);
|
||||
}
|
||||
if (is_weight<mp11::mp_at_c<L, n>>::value) {
|
||||
// 0, n already covered
|
||||
if (is_sample<mp11::mp_at_c<L, (n - 1)>>::value) return std::make_pair(n, n - 1);
|
||||
return std::make_pair(n, -1);
|
||||
}
|
||||
if (is_sample<mp11::mp_at_c<L, n>>::value) {
|
||||
// n, 0 already covered
|
||||
if (is_weight<mp11::mp_at_c<L, (n - 1)>>::value) return std::make_pair(n - 1, n);
|
||||
return std::make_pair(-1, n);
|
||||
}
|
||||
return std::make_pair(-1, -1);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
void fill_storage(mp11::mp_int<-1>, mp11::mp_int<-1>, T&& t, U&&) {
|
||||
static_if<is_incrementable<remove_cvref_t<T>>>(
|
||||
[](auto&& t) { ++t; }, [](auto&& t) { t(); }, std::forward<T>(t));
|
||||
}
|
||||
|
||||
template <class IW, class T, class U>
|
||||
void fill_storage(IW, mp11::mp_int<-1>, T&& t, U&& args) {
|
||||
static_if<is_incrementable<remove_cvref_t<T>>>(
|
||||
[](auto&& t, const auto& w) { t += w; },
|
||||
[](auto&& t, const auto& w) {
|
||||
#ifdef BOOST_HISTOGRAM_WITH_ACCUMULATORS_SUPPORT
|
||||
static_if<is_accumulator_set<remove_cvref_t<T>>>(
|
||||
[w](auto&& t) { t(::boost::accumulators::weight = w); },
|
||||
[w](auto&& t) { t(w); }, t);
|
||||
#else
|
||||
t(w);
|
||||
#endif
|
||||
},
|
||||
std::forward<T>(t), std::get<IW::value>(args).value);
|
||||
}
|
||||
|
||||
template <class IS, class T, class U>
|
||||
void fill_storage(mp11::mp_int<-1>, IS, T&& t, U&& args) {
|
||||
mp11::tuple_apply([&t](auto&&... args) { t(args...); },
|
||||
std::get<IS::value>(args).value);
|
||||
}
|
||||
|
||||
template <class IW, class IS, class T, class U>
|
||||
void fill_storage(IW, IS, T&& t, U&& args) {
|
||||
mp11::tuple_apply(
|
||||
[&](auto&&... args2) { t(std::get<IW::value>(args).value, args2...); },
|
||||
std::get<IS::value>(args).value);
|
||||
}
|
||||
|
||||
template <class S, class A, class... Us>
|
||||
auto fill(S& storage, A& axes, const std::tuple<Us...>& args) {
|
||||
constexpr auto iws = weight_sample_indices<Us...>();
|
||||
constexpr unsigned n = sizeof...(Us) - (iws.first > -1) - (iws.second > -1);
|
||||
constexpr unsigned i = (iws.first == 0 || iws.second == 0)
|
||||
? (iws.first == 1 || iws.second == 1 ? 2 : 1)
|
||||
: 0;
|
||||
optional_index idx = args_to_index<i, n>(has_growing_axis<A>(), storage, axes, args);
|
||||
if (idx) {
|
||||
fill_storage(mp11::mp_int<iws.first>(), mp11::mp_int<iws.second>(), storage[*idx],
|
||||
args);
|
||||
return storage.begin() + *idx;
|
||||
}
|
||||
return storage.end();
|
||||
}
|
||||
|
||||
template <typename A, typename... Us>
|
||||
optional_index at(const A& axes, const std::tuple<Us...>& args) {
|
||||
if (get_size(axes) != sizeof...(Us))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("number of arguments != histogram rank"));
|
||||
optional_index idx;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Us)>>([&](auto I) {
|
||||
// axes_get works with static and dynamic axes
|
||||
linearize_index(idx, axis_get<I>(axes),
|
||||
static_cast<axis::index_type>(std::get<I>(args)));
|
||||
});
|
||||
return idx;
|
||||
}
|
||||
|
||||
template <typename A, typename U>
|
||||
optional_index at(const A& axes, const U& args) {
|
||||
if (get_size(axes) != get_size(args))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("number of arguments != histogram rank"));
|
||||
optional_index idx;
|
||||
using std::begin;
|
||||
auto it = begin(args);
|
||||
for_each_axis(axes, [&](const auto& a) {
|
||||
linearize_index(idx, a, static_cast<axis::index_type>(*it++));
|
||||
});
|
||||
return idx;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
436
macx64/include/boost/histogram/detail/meta.hpp
Normal file
436
macx64/include/boost/histogram/detail/meta.hpp
Normal file
@@ -0,0 +1,436 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_META_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_META_HPP
|
||||
|
||||
/* Most of the histogram code is generic and works for any number of axes. Buffers with a
|
||||
* fixed maximum capacity are used in some places, which have a size equal to the rank of
|
||||
* a histogram. The buffers are statically allocated to improve performance, which means
|
||||
* that they need a preset maximum capacity. 32 seems like a safe upper limit for the rank
|
||||
* (you can nevertheless increase it here if necessary): the simplest non-trivial axis has
|
||||
* 2 bins; even if counters are used which need only a byte of storage per bin, this still
|
||||
* corresponds to 4 GB of storage.
|
||||
*/
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_AXES_LIMIT
|
||||
#define BOOST_HISTOGRAM_DETAIL_AXES_LIMIT 32
|
||||
#endif
|
||||
|
||||
#include <boost/config/workaround.hpp>
|
||||
#if BOOST_WORKAROUND(BOOST_GCC, >= 60000)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wnoexcept-type"
|
||||
#endif
|
||||
#include <boost/callable_traits/args.hpp>
|
||||
#include <boost/callable_traits/return_type.hpp>
|
||||
#if BOOST_WORKAROUND(BOOST_GCC, >= 60000)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#include <array>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/mp11/function.hpp>
|
||||
#include <boost/mp11/integer_sequence.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
||||
template <class T, class U>
|
||||
using convert_integer = mp11::mp_if<std::is_integral<remove_cvref_t<T>>, U, T>;
|
||||
|
||||
// to be replaced by official version from mp11
|
||||
template <class E, template <class...> class F, class... Ts>
|
||||
using mp_eval_or = mp11::mp_eval_if_c<!(mp11::mp_valid<F, Ts...>::value), E, F, Ts...>;
|
||||
|
||||
template <class T1, class T2>
|
||||
using copy_qualifiers = mp11::mp_if<
|
||||
std::is_rvalue_reference<T1>, T2&&,
|
||||
mp11::mp_if<std::is_lvalue_reference<T1>,
|
||||
mp11::mp_if<std::is_const<typename std::remove_reference<T1>::type>,
|
||||
const T2&, T2&>,
|
||||
mp11::mp_if<std::is_const<T1>, const T2, T2>>>;
|
||||
|
||||
template <class L>
|
||||
using mp_last = mp11::mp_at_c<L, (mp11::mp_size<L>::value - 1)>;
|
||||
|
||||
template <class T, class Args = boost::callable_traits::args_t<T>>
|
||||
using args_type =
|
||||
mp11::mp_if<std::is_member_function_pointer<T>, mp11::mp_pop_front<Args>, Args>;
|
||||
|
||||
template <class T, std::size_t N = 0>
|
||||
using arg_type = typename mp11::mp_at_c<args_type<T>, N>;
|
||||
|
||||
template <class T>
|
||||
using return_type = typename boost::callable_traits::return_type<T>::type;
|
||||
|
||||
template <class F, class V,
|
||||
class T = copy_qualifiers<V, mp11::mp_first<remove_cvref_t<V>>>>
|
||||
using visitor_return_type = decltype(std::declval<F>()(std::declval<T>()));
|
||||
|
||||
template <bool B, typename T, typename F, typename... Ts>
|
||||
constexpr decltype(auto) static_if_c(T&& t, F&& f, Ts&&... ts) {
|
||||
return std::get<(B ? 0 : 1)>(std::forward_as_tuple(
|
||||
std::forward<T>(t), std::forward<F>(f)))(std::forward<Ts>(ts)...);
|
||||
}
|
||||
|
||||
template <typename B, typename... Ts>
|
||||
constexpr decltype(auto) static_if(Ts&&... ts) {
|
||||
return static_if_c<B::value>(std::forward<Ts>(ts)...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T lowest() {
|
||||
return std::numeric_limits<T>::lowest();
|
||||
}
|
||||
|
||||
template <>
|
||||
constexpr double lowest() {
|
||||
return -std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
template <>
|
||||
constexpr float lowest() {
|
||||
return -std::numeric_limits<float>::infinity();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T highest() {
|
||||
return std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
template <>
|
||||
constexpr double highest() {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
template <>
|
||||
constexpr float highest() {
|
||||
return std::numeric_limits<float>::infinity();
|
||||
}
|
||||
|
||||
template <std::size_t I, class T, std::size_t... N>
|
||||
decltype(auto) tuple_slice_impl(T&& t, mp11::index_sequence<N...>) {
|
||||
return std::forward_as_tuple(std::get<(N + I)>(std::forward<T>(t))...);
|
||||
}
|
||||
|
||||
template <std::size_t I, std::size_t N, class T>
|
||||
decltype(auto) tuple_slice(T&& t) {
|
||||
static_assert(I + N <= mp11::mp_size<remove_cvref_t<T>>::value,
|
||||
"I and N must describe a slice");
|
||||
return tuple_slice_impl<I>(std::forward<T>(t), mp11::make_index_sequence<N>{});
|
||||
}
|
||||
|
||||
#define BOOST_HISTOGRAM_DETECT(name, cond) \
|
||||
template <class T, class = decltype(cond)> \
|
||||
struct name##_impl {}; \
|
||||
template <class T> \
|
||||
using name = typename mp11::mp_valid<name##_impl, T>
|
||||
|
||||
#define BOOST_HISTOGRAM_DETECT_BINARY(name, cond) \
|
||||
template <class T, class U, class = decltype(cond)> \
|
||||
struct name##_impl {}; \
|
||||
template <class T, class U = T> \
|
||||
using name = typename mp11::mp_valid<name##_impl, T, U>
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_metadata, (std::declval<T&>().metadata()));
|
||||
|
||||
// resize has two overloads, trying to get pmf in this case always fails
|
||||
BOOST_HISTOGRAM_DETECT(has_method_resize, (std::declval<T&>().resize(0)));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_size, &T::size);
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_clear, &T::clear);
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_lower, &T::lower);
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_value, &T::value);
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_update, (&T::update));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_reset, (std::declval<T>().reset(0)));
|
||||
|
||||
template <typename T>
|
||||
using get_value_method_return_type_impl = decltype(std::declval<T&>().value(0));
|
||||
|
||||
template <typename T, typename R>
|
||||
using has_method_value_with_convertible_return_type =
|
||||
typename std::is_convertible<mp_eval_or<void, get_value_method_return_type_impl, T>,
|
||||
R>::type;
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_options, (&T::options));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_allocator, &T::get_allocator);
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_indexable, (std::declval<T&>()[0]));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_transform, (&T::forward, &T::inverse));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_indexable_container,
|
||||
(std::declval<T>()[0], &T::size, std::begin(std::declval<T>()),
|
||||
std::end(std::declval<T>())));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_vector_like,
|
||||
(std::declval<T>()[0], &T::size, std::declval<T>().resize(0),
|
||||
std::begin(std::declval<T>()), std::end(std::declval<T>())));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_array_like,
|
||||
(std::declval<T>()[0], &T::size, std::tuple_size<T>::value,
|
||||
std::begin(std::declval<T>()), std::end(std::declval<T>())));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_map_like,
|
||||
(std::declval<typename T::key_type>(),
|
||||
std::declval<typename T::mapped_type>(),
|
||||
std::begin(std::declval<T>()), std::end(std::declval<T>())));
|
||||
|
||||
// ok: is_axis is false for axis::variant, operator() is templated
|
||||
BOOST_HISTOGRAM_DETECT(is_axis, (&T::size, &T::index));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_iterable,
|
||||
(std::begin(std::declval<T&>()), std::end(std::declval<T&>())));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_iterator,
|
||||
(typename std::iterator_traits<T>::iterator_category()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_streamable,
|
||||
(std::declval<std::ostream&>() << std::declval<T&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_incrementable, (++std::declval<T&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_operator_preincrement, (++std::declval<T&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT_BINARY(has_operator_equal,
|
||||
(std::declval<const T&>() == std::declval<const U&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT_BINARY(has_operator_radd,
|
||||
(std::declval<T&>() += std::declval<U&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rsub,
|
||||
(std::declval<T&>() -= std::declval<U&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rmul,
|
||||
(std::declval<T&>() *= std::declval<U&>()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rdiv,
|
||||
(std::declval<T&>() /= std::declval<U&>()));
|
||||
|
||||
template <typename T>
|
||||
using is_storage =
|
||||
mp11::mp_bool<(is_indexable_container<T>::value && has_method_reset<T>::value)>;
|
||||
|
||||
template <typename T>
|
||||
struct is_tuple_impl : std::false_type {};
|
||||
|
||||
template <typename... Ts>
|
||||
struct is_tuple_impl<std::tuple<Ts...>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using is_tuple = typename is_tuple_impl<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct is_axis_variant_impl : std::false_type {};
|
||||
|
||||
template <typename... Ts>
|
||||
struct is_axis_variant_impl<axis::variant<Ts...>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using is_axis_variant = typename is_axis_variant_impl<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using is_any_axis = mp11::mp_or<is_axis<T>, is_axis_variant<T>>;
|
||||
|
||||
template <typename T>
|
||||
using is_sequence_of_axis = mp11::mp_and<is_iterable<T>, is_axis<mp11::mp_first<T>>>;
|
||||
|
||||
template <typename T>
|
||||
using is_sequence_of_axis_variant =
|
||||
mp11::mp_and<is_iterable<T>, is_axis_variant<mp11::mp_first<T>>>;
|
||||
|
||||
template <typename T>
|
||||
using is_sequence_of_any_axis =
|
||||
mp11::mp_and<is_iterable<T>, is_any_axis<mp11::mp_first<T>>>;
|
||||
|
||||
template <typename T>
|
||||
struct is_weight_impl : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_weight_impl<weight_type<T>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using is_weight = is_weight_impl<remove_cvref_t<T>>;
|
||||
|
||||
template <typename T>
|
||||
struct is_sample_impl : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_sample_impl<sample_type<T>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using is_sample = is_sample_impl<remove_cvref_t<T>>;
|
||||
|
||||
// poor-mans concept checks
|
||||
template <class T, class = std::enable_if_t<is_iterator<remove_cvref_t<T>>::value>>
|
||||
struct requires_iterator {};
|
||||
|
||||
template <class T, class = std::enable_if_t<is_iterable<remove_cvref_t<T>>::value>>
|
||||
struct requires_iterable {};
|
||||
|
||||
template <class T, class = std::enable_if_t<is_axis<remove_cvref_t<T>>::value>>
|
||||
struct requires_axis {};
|
||||
|
||||
template <class T, class = std::enable_if_t<is_any_axis<remove_cvref_t<T>>::value>>
|
||||
struct requires_any_axis {};
|
||||
|
||||
template <class T,
|
||||
class = std::enable_if_t<is_sequence_of_axis<remove_cvref_t<T>>::value>>
|
||||
struct requires_sequence_of_axis {};
|
||||
|
||||
template <class T,
|
||||
class = std::enable_if_t<is_sequence_of_axis_variant<remove_cvref_t<T>>::value>>
|
||||
struct requires_sequence_of_axis_variant {};
|
||||
|
||||
template <class T,
|
||||
class = std::enable_if_t<is_sequence_of_any_axis<remove_cvref_t<T>>::value>>
|
||||
struct requires_sequence_of_any_axis {};
|
||||
|
||||
template <class T,
|
||||
class = std::enable_if_t<is_any_axis<mp11::mp_first<remove_cvref_t<T>>>::value>>
|
||||
struct requires_axes {};
|
||||
|
||||
template <class T, class U, class = std::enable_if_t<std::is_convertible<T, U>::value>>
|
||||
struct requires_convertible {};
|
||||
|
||||
template <class T>
|
||||
auto make_default(const T& t) {
|
||||
return static_if<has_allocator<T>>([](const auto& t) { return T(t.get_allocator()); },
|
||||
[](const auto&) { return T(); }, t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
using tuple_size_t = typename std::tuple_size<T>::type;
|
||||
|
||||
template <class T>
|
||||
constexpr std::size_t get_size_impl(std::true_type, const T&) noexcept {
|
||||
return std::tuple_size<T>::value;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t get_size_impl(std::false_type, const T& t) noexcept {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
return static_cast<std::size_t>(std::distance(begin(t), end(t)));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t get_size(const T& t) noexcept {
|
||||
return get_size_impl(mp11::mp_valid<tuple_size_t, T>(), t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
using buffer_size =
|
||||
mp_eval_or<std::integral_constant<std::size_t, BOOST_HISTOGRAM_DETAIL_AXES_LIMIT>,
|
||||
tuple_size_t, T>;
|
||||
|
||||
template <class T, std::size_t N>
|
||||
class sub_array : public std::array<T, N> {
|
||||
public:
|
||||
explicit sub_array(std::size_t s) : size_(s) {}
|
||||
sub_array(std::size_t s, T value) : size_(s) { std::array<T, N>::fill(value); }
|
||||
|
||||
// need to override both versions of std::array
|
||||
auto end() noexcept { return std::array<T, N>::begin() + size_; }
|
||||
auto end() const noexcept { return std::array<T, N>::begin() + size_; }
|
||||
|
||||
auto size() const noexcept { return size_; }
|
||||
|
||||
private:
|
||||
std::size_t size_ = N;
|
||||
};
|
||||
|
||||
template <class U, class T>
|
||||
using stack_buffer = sub_array<U, buffer_size<T>::value>;
|
||||
|
||||
template <class U, class T, class... Ts>
|
||||
auto make_stack_buffer(const T& t, Ts&&... ts) {
|
||||
return stack_buffer<U, T>(get_size(t), std::forward<Ts>(ts)...);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr bool relaxed_equal(const T& a, const T& b) noexcept {
|
||||
return static_if<has_operator_equal<T>>(
|
||||
[](const auto& a, const auto& b) { return a == b; },
|
||||
[](const auto&, const auto&) { return true; }, a, b);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
using get_scale_type_helper = typename T::value_type;
|
||||
|
||||
template <class T>
|
||||
using get_scale_type = mp_eval_or<T, detail::get_scale_type_helper, T>;
|
||||
|
||||
struct one_unit {};
|
||||
|
||||
template <class T>
|
||||
T operator*(T&& t, const one_unit&) {
|
||||
return std::forward<T>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T operator/(T&& t, const one_unit&) {
|
||||
return std::forward<T>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
using get_unit_type_helper = typename T::unit_type;
|
||||
|
||||
template <class T>
|
||||
using get_unit_type = mp_eval_or<one_unit, detail::get_unit_type_helper, T>;
|
||||
|
||||
template <class T, class R = get_scale_type<T>>
|
||||
R get_scale(const T& t) {
|
||||
return t / get_unit_type<T>();
|
||||
}
|
||||
|
||||
template <class T, class Default>
|
||||
using replace_default = mp11::mp_if<std::is_same<T, use_default>, Default, T>;
|
||||
|
||||
template <class T, class U>
|
||||
using is_convertible_helper =
|
||||
mp11::mp_apply<mp11::mp_all, mp11::mp_transform<std::is_convertible, T, U>>;
|
||||
|
||||
template <class T, class U>
|
||||
using is_convertible = mp_eval_or<std::false_type, is_convertible_helper, T, U>;
|
||||
|
||||
template <class T>
|
||||
auto make_unsigned_impl(std::true_type, const T t) noexcept {
|
||||
return static_cast<typename std::make_unsigned<T>::type>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto make_unsigned_impl(std::false_type, const T t) noexcept {
|
||||
return t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto make_unsigned(const T t) noexcept {
|
||||
return make_unsigned_impl(std::is_integral<T>{}, t);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
122
macx64/include/boost/histogram/fwd.hpp
Normal file
122
macx64/include/boost/histogram/fwd.hpp
Normal file
@@ -0,0 +1,122 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_FWD_HPP
|
||||
#define BOOST_HISTOGRAM_FWD_HPP
|
||||
|
||||
/**
|
||||
\file boost/histogram/fwd.hpp
|
||||
Forward declarations, tag types and type aliases.
|
||||
*/
|
||||
|
||||
#include <boost/core/use_default.hpp>
|
||||
#include <boost/histogram/detail/attribute.hpp> // BOOST_HISTOGRAM_DETAIL_NODISCARD
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
/// Tag type to indicate use of a default type
|
||||
using boost::use_default;
|
||||
|
||||
namespace axis {
|
||||
|
||||
/// Integral type for axis indices
|
||||
using index_type = int;
|
||||
|
||||
/// Real type for axis indices
|
||||
using real_index_type = double;
|
||||
|
||||
/// Empty metadata type
|
||||
struct null_type {};
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
namespace transform {
|
||||
struct id;
|
||||
struct log;
|
||||
struct sqrt;
|
||||
struct pow;
|
||||
} // namespace transform
|
||||
|
||||
template <class Value = double, class Transform = use_default,
|
||||
class MetaData = use_default, class Options = use_default>
|
||||
class regular;
|
||||
|
||||
template <class Value = int, class MetaData = use_default, class Options = use_default>
|
||||
class integer;
|
||||
|
||||
template <class Value = double, class MetaData = use_default, class Options = use_default,
|
||||
class Allocator = std::allocator<Value>>
|
||||
class variable;
|
||||
|
||||
template <class Value = int, class MetaData = use_default, class Options = use_default,
|
||||
class Allocator = std::allocator<Value>>
|
||||
class category;
|
||||
|
||||
template <class... Ts>
|
||||
class variant;
|
||||
|
||||
#endif // BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
} // namespace axis
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
template <class T>
|
||||
struct weight_type;
|
||||
|
||||
template <class T>
|
||||
struct sample_type;
|
||||
|
||||
namespace accumulators {
|
||||
template <class Value = double>
|
||||
class sum;
|
||||
template <class Value = double>
|
||||
class weighted_sum;
|
||||
template <class Value = double>
|
||||
class mean;
|
||||
template <class Value = double>
|
||||
class weighted_mean;
|
||||
} // namespace accumulators
|
||||
|
||||
struct unsafe_access;
|
||||
|
||||
template <class Allocator = std::allocator<char>>
|
||||
class unlimited_storage;
|
||||
|
||||
template <class T>
|
||||
class storage_adaptor;
|
||||
|
||||
#endif // BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
/// Vector-like storage for fast zero-overhead access to cells
|
||||
template <class T, class A = std::allocator<T>>
|
||||
using dense_storage = storage_adaptor<std::vector<T, A>>;
|
||||
|
||||
/// Default storage, optimized for unweighted histograms
|
||||
using default_storage = unlimited_storage<>;
|
||||
|
||||
/// Dense storage which tracks sums of weights and a variance estimate
|
||||
using weight_storage = dense_storage<accumulators::weighted_sum<>>;
|
||||
|
||||
/// Dense storage which tracks means of samples in each cell
|
||||
using profile_storage = dense_storage<accumulators::mean<>>;
|
||||
|
||||
/// Dense storage which tracks means of weighted samples in each cell
|
||||
using weighted_profile_storage = dense_storage<accumulators::weighted_mean<>>;
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
template <class Axes, class Storage = default_storage>
|
||||
class BOOST_HISTOGRAM_DETAIL_NODISCARD histogram;
|
||||
|
||||
#endif
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
425
macx64/include/boost/histogram/histogram.hpp
Normal file
425
macx64/include/boost/histogram/histogram.hpp
Normal file
@@ -0,0 +1,425 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_HISTOGRAM_HPP
|
||||
#define BOOST_HISTOGRAM_HISTOGRAM_HPP
|
||||
|
||||
#include <boost/histogram/detail/axes.hpp>
|
||||
#include <boost/histogram/detail/common_type.hpp>
|
||||
#include <boost/histogram/detail/linearize.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
/** Central class of the histogram library.
|
||||
|
||||
Histogram uses the call operator to insert data, like the
|
||||
[Boost.Accumulators](https://www.boost.org/doc/libs/develop/doc/html/accumulators.html).
|
||||
|
||||
Use factory functions (see
|
||||
[make_histogram.hpp](histogram/reference.html#header.boost.histogram.make_histogram_hpp)
|
||||
and
|
||||
[make_profile.hpp](histogram/reference.html#header.boost.histogram.make_profile_hpp)) to
|
||||
conveniently create histograms rather than calling the ctors directly.
|
||||
|
||||
Use the [indexed](boost/histogram/indexed.html) range generator to iterate over filled
|
||||
histograms, which is convenient and faster than hand-written loops for multi-dimensional
|
||||
histograms.
|
||||
|
||||
@tparam Axes std::tuple of axis types OR std::vector of an axis type or axis::variant
|
||||
@tparam Storage class that implements the storage interface
|
||||
*/
|
||||
template <class Axes, class Storage>
|
||||
class histogram {
|
||||
public:
|
||||
static_assert(mp11::mp_size<Axes>::value > 0, "at least one axis required");
|
||||
static_assert(std::is_same<detail::remove_cvref_t<Storage>, Storage>::value,
|
||||
"Storage may not be a reference or const or volatile");
|
||||
|
||||
public:
|
||||
using axes_type = Axes;
|
||||
using storage_type = Storage;
|
||||
using value_type = typename storage_type::value_type;
|
||||
// typedefs for boost::range_iterator
|
||||
using iterator = typename storage_type::iterator;
|
||||
using const_iterator = typename storage_type::const_iterator;
|
||||
|
||||
histogram() = default;
|
||||
histogram(const histogram& rhs) = default;
|
||||
histogram(histogram&& rhs) = default;
|
||||
histogram& operator=(const histogram& rhs) = default;
|
||||
histogram& operator=(histogram&& rhs) = default;
|
||||
|
||||
template <class A, class S>
|
||||
explicit histogram(histogram<A, S>&& rhs) : storage_(std::move(rhs.storage_)) {
|
||||
detail::axes_assign(axes_, rhs.axes_);
|
||||
}
|
||||
|
||||
template <class A, class S>
|
||||
explicit histogram(const histogram<A, S>& rhs) : storage_(rhs.storage_) {
|
||||
detail::axes_assign(axes_, rhs.axes_);
|
||||
}
|
||||
|
||||
template <class A, class S>
|
||||
histogram& operator=(histogram<A, S>&& rhs) {
|
||||
detail::axes_assign(axes_, std::move(rhs.axes_));
|
||||
storage_ = std::move(rhs.storage_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class A, class S>
|
||||
histogram& operator=(const histogram<A, S>& rhs) {
|
||||
detail::axes_assign(axes_, rhs.axes_);
|
||||
storage_ = rhs.storage_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class A, class S>
|
||||
histogram(A&& a, S&& s) : axes_(std::forward<A>(a)), storage_(std::forward<S>(s)) {
|
||||
storage_.reset(detail::bincount(axes_));
|
||||
}
|
||||
|
||||
template <class A, class = detail::requires_axes<A>>
|
||||
explicit histogram(A&& a) : histogram(std::forward<A>(a), storage_type()) {}
|
||||
|
||||
/// Number of axes (dimensions).
|
||||
constexpr unsigned rank() const noexcept {
|
||||
return static_cast<unsigned>(detail::get_size(axes_));
|
||||
}
|
||||
|
||||
/// Total number of bins (including underflow/overflow).
|
||||
std::size_t size() const noexcept { return storage_.size(); }
|
||||
|
||||
/// Reset all bins to default initialized values.
|
||||
void reset() { storage_.reset(storage_.size()); }
|
||||
|
||||
/// Get N-th axis using a compile-time number.
|
||||
/// This version is more efficient than the one accepting a run-time number.
|
||||
template <unsigned N = 0>
|
||||
decltype(auto) axis(std::integral_constant<unsigned, N> = {}) const {
|
||||
detail::axis_index_is_valid(axes_, N);
|
||||
return detail::axis_get<N>(axes_);
|
||||
}
|
||||
|
||||
/// Get N-th axis with run-time number.
|
||||
/// Use version that accepts a compile-time number, if possible.
|
||||
decltype(auto) axis(unsigned i) const {
|
||||
detail::axis_index_is_valid(axes_, i);
|
||||
return detail::axis_get(axes_, i);
|
||||
}
|
||||
|
||||
/// Apply unary functor/function to each axis.
|
||||
template <class Unary>
|
||||
auto for_each_axis(Unary&& unary) const {
|
||||
return detail::for_each_axis(axes_, std::forward<Unary>(unary));
|
||||
}
|
||||
|
||||
/** 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`.
|
||||
|
||||
__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.
|
||||
|
||||
__Optional weight__
|
||||
|
||||
An optional weight can be passed as the first or last argument
|
||||
with the [weight](boost/histogram/weight.html) helper function. Compilation fails if
|
||||
the storage elements do not support weights.
|
||||
|
||||
__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](boost/histogram/sample.html) 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::make_tuple(ts...));
|
||||
}
|
||||
|
||||
/// Fill histogram with values, an optional weight, and/or a sample from a `std::tuple`.
|
||||
template <class... Ts>
|
||||
auto operator()(const std::tuple<Ts...>& t) {
|
||||
return detail::fill(storage_, axes_, t);
|
||||
}
|
||||
|
||||
/// Access cell value at integral indices.
|
||||
/**
|
||||
You can pass indices as individual arguments, as a std::tuple of integers, or as an
|
||||
interable range of integers. Passing the wrong number of arguments causes a throw of
|
||||
std::invalid_argument. Passing an index which is out of bounds causes a throw of
|
||||
std::out_of_range.
|
||||
*/
|
||||
template <class... Ts>
|
||||
decltype(auto) at(axis::index_type t, Ts... ts) {
|
||||
return at(std::forward_as_tuple(t, ts...));
|
||||
}
|
||||
|
||||
/// Access cell value at integral indices (read-only).
|
||||
/// @copydoc at(axis::index_type t, Ts... ts)
|
||||
template <class... Ts>
|
||||
decltype(auto) at(axis::index_type t, Ts... ts) const {
|
||||
return at(std::forward_as_tuple(t, ts...));
|
||||
}
|
||||
|
||||
/// Access cell value at integral indices stored in `std::tuple`.
|
||||
/// @copydoc at(axis::index_type t, Ts... ts)
|
||||
template <typename... Ts>
|
||||
decltype(auto) at(const std::tuple<Ts...>& t) {
|
||||
const auto idx = detail::at(axes_, t);
|
||||
if (!idx) BOOST_THROW_EXCEPTION(std::out_of_range("indices out of bounds"));
|
||||
return storage_[*idx];
|
||||
}
|
||||
|
||||
/// Access cell value at integral indices stored in `std::tuple` (read-only).
|
||||
/// @copydoc at(axis::index_type t, Ts... ts)
|
||||
template <typename... Ts>
|
||||
decltype(auto) at(const std::tuple<Ts...>& t) const {
|
||||
const auto idx = detail::at(axes_, t);
|
||||
if (!idx) BOOST_THROW_EXCEPTION(std::out_of_range("indices out of bounds"));
|
||||
return storage_[*idx];
|
||||
}
|
||||
|
||||
/// Access cell value at integral indices stored in iterable.
|
||||
/// @copydoc at(axis::index_type t, Ts... ts)
|
||||
template <class Iterable, class = detail::requires_iterable<Iterable>>
|
||||
decltype(auto) at(const Iterable& c) {
|
||||
const auto idx = detail::at(axes_, c);
|
||||
if (!idx) BOOST_THROW_EXCEPTION(std::out_of_range("indices out of bounds"));
|
||||
return storage_[*idx];
|
||||
}
|
||||
|
||||
/// Access cell value at integral indices stored in iterable (read-only).
|
||||
/// @copydoc at(axis::index_type t, Ts... ts)
|
||||
template <class Iterable, class = detail::requires_iterable<Iterable>>
|
||||
decltype(auto) at(const Iterable& c) const {
|
||||
const auto idx = detail::at(axes_, c);
|
||||
if (!idx) BOOST_THROW_EXCEPTION(std::out_of_range("indices out of bounds"));
|
||||
return storage_[*idx];
|
||||
}
|
||||
|
||||
/// Access value at index (number for rank = 1, else `std::tuple` or iterable).
|
||||
template <class T>
|
||||
decltype(auto) operator[](const T& t) {
|
||||
return at(t);
|
||||
}
|
||||
|
||||
/// @copydoc operator[]
|
||||
template <class T>
|
||||
decltype(auto) operator[](const T& t) const {
|
||||
return at(t);
|
||||
}
|
||||
|
||||
/// Equality operator, tests equality for all axes and the storage.
|
||||
template <class A, class S>
|
||||
bool operator==(const histogram<A, S>& rhs) const noexcept {
|
||||
return detail::axes_equal(axes_, rhs.axes_) && storage_ == rhs.storage_;
|
||||
}
|
||||
|
||||
/// Negation of the equality operator.
|
||||
template <class A, class S>
|
||||
bool operator!=(const histogram<A, S>& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
/// Add values of another histogram.
|
||||
template <class A, class S>
|
||||
histogram& operator+=(const histogram<A, S>& rhs) {
|
||||
static_assert(detail::has_operator_radd<value_type,
|
||||
typename histogram<A, S>::value_type>::value,
|
||||
"cell value does not support adding value of right-hand-side");
|
||||
if (!detail::axes_equal(axes_, rhs.axes_))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("axes of histograms differ"));
|
||||
auto rit = rhs.storage_.begin();
|
||||
std::for_each(storage_.begin(), storage_.end(), [&rit](auto&& x) { x += *rit++; });
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Subtract values of another histogram.
|
||||
template <class A, class S>
|
||||
histogram& operator-=(const histogram<A, S>& rhs) {
|
||||
static_assert(detail::has_operator_rsub<value_type,
|
||||
typename histogram<A, S>::value_type>::value,
|
||||
"cell value does not support subtracting value of right-hand-side");
|
||||
if (!detail::axes_equal(axes_, rhs.axes_))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("axes of histograms differ"));
|
||||
auto rit = rhs.storage_.begin();
|
||||
std::for_each(storage_.begin(), storage_.end(), [&rit](auto&& x) { x -= *rit++; });
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Multiply by values of another histogram.
|
||||
template <class A, class S>
|
||||
histogram& operator*=(const histogram<A, S>& rhs) {
|
||||
static_assert(detail::has_operator_rmul<value_type,
|
||||
typename histogram<A, S>::value_type>::value,
|
||||
"cell value does not support multiplying by value of right-hand-side");
|
||||
if (!detail::axes_equal(axes_, rhs.axes_))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("axes of histograms differ"));
|
||||
auto rit = rhs.storage_.begin();
|
||||
std::for_each(storage_.begin(), storage_.end(), [&rit](auto&& x) { x *= *rit++; });
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Divide by values of another histogram.
|
||||
template <class A, class S>
|
||||
histogram& operator/=(const histogram<A, S>& rhs) {
|
||||
static_assert(detail::has_operator_rdiv<value_type,
|
||||
typename histogram<A, S>::value_type>::value,
|
||||
"cell value does not support dividing by value of right-hand-side");
|
||||
if (!detail::axes_equal(axes_, rhs.axes_))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("axes of histograms differ"));
|
||||
auto rit = rhs.storage_.begin();
|
||||
std::for_each(storage_.begin(), storage_.end(), [&rit](auto&& x) { x /= *rit++; });
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Multiply all values with a scalar.
|
||||
template <class V = value_type,
|
||||
class = std::enable_if_t<detail::has_operator_rmul<V, double>::value>>
|
||||
histogram& operator*=(const double x) {
|
||||
// use special implementation of scaling if available
|
||||
detail::static_if<detail::has_operator_rmul<storage_type, double>>(
|
||||
[](storage_type& s, auto x) { s *= x; },
|
||||
[](storage_type& s, auto x) {
|
||||
for (auto&& si : s) si *= x;
|
||||
},
|
||||
storage_, x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Divide all values by a scalar.
|
||||
template <class V = value_type,
|
||||
class = std::enable_if_t<detail::has_operator_rmul<V, double>::value>>
|
||||
histogram& operator/=(const double x) {
|
||||
return operator*=(1.0 / x);
|
||||
}
|
||||
|
||||
/// 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_;
|
||||
|
||||
template <class A, class S>
|
||||
friend class histogram;
|
||||
friend struct unsafe_access;
|
||||
};
|
||||
|
||||
template <class A1, class S1, class A2, class S2>
|
||||
auto operator+(const histogram<A1, S1>& a, const histogram<A2, S2>& b) {
|
||||
auto r = histogram<detail::common_axes<A1, A2>, detail::common_storage<S1, S2>>(a);
|
||||
return r += b;
|
||||
}
|
||||
|
||||
template <class A1, class S1, class A2, class S2>
|
||||
auto operator*(const histogram<A1, S1>& a, const histogram<A2, S2>& b) {
|
||||
auto r = histogram<detail::common_axes<A1, A2>, detail::common_storage<S1, S2>>(a);
|
||||
return r *= b;
|
||||
}
|
||||
|
||||
template <class A1, class S1, class A2, class S2>
|
||||
auto operator-(const histogram<A1, S1>& a, const histogram<A2, S2>& b) {
|
||||
auto r = histogram<detail::common_axes<A1, A2>, detail::common_storage<S1, S2>>(a);
|
||||
return r -= b;
|
||||
}
|
||||
|
||||
template <class A1, class S1, class A2, class S2>
|
||||
auto operator/(const histogram<A1, S1>& a, const histogram<A2, S2>& b) {
|
||||
auto r = histogram<detail::common_axes<A1, A2>, detail::common_storage<S1, S2>>(a);
|
||||
return r /= b;
|
||||
}
|
||||
|
||||
template <class A, class S>
|
||||
auto operator*(const histogram<A, S>& h, double x) {
|
||||
auto r = histogram<A, detail::common_storage<S, dense_storage<double>>>(h);
|
||||
return r *= x;
|
||||
}
|
||||
|
||||
template <class A, class S>
|
||||
auto operator*(double x, const histogram<A, S>& h) {
|
||||
return h * x;
|
||||
}
|
||||
|
||||
template <class A, class S>
|
||||
auto operator/(const histogram<A, S>& h, double x) {
|
||||
return h * (1.0 / x);
|
||||
}
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
|
||||
template <class Axes>
|
||||
histogram(Axes&& axes)->histogram<detail::remove_cvref_t<Axes>, default_storage>;
|
||||
|
||||
template <class Axes, class Storage>
|
||||
histogram(Axes&& axes, Storage&& storage)
|
||||
->histogram<detail::remove_cvref_t<Axes>, detail::remove_cvref_t<Storage>>;
|
||||
|
||||
#endif
|
||||
|
||||
/// Helper function to mark argument as weight.
|
||||
/// @param t argument to be forward to the histogram.
|
||||
template <typename T>
|
||||
auto weight(T&& t) noexcept {
|
||||
return weight_type<T>{std::forward<T>(t)};
|
||||
}
|
||||
|
||||
/// Helper function to mark arguments as sample.
|
||||
/// @param ts arguments to be forwarded to the accumulator.
|
||||
template <typename... Ts>
|
||||
auto sample(Ts&&... ts) noexcept {
|
||||
return sample_type<std::tuple<Ts...>>{std::forward_as_tuple(std::forward<Ts>(ts)...)};
|
||||
}
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
template <class T>
|
||||
struct weight_type {
|
||||
T value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct sample_type {
|
||||
T value;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
220
macx64/include/boost/histogram/indexed.hpp
Normal file
220
macx64/include/boost/histogram/indexed.hpp
Normal file
@@ -0,0 +1,220 @@
|
||||
// Copyright 2015-2016 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_INDEXED_HPP
|
||||
#define BOOST_HISTOGRAM_INDEXED_HPP
|
||||
|
||||
#include <boost/histogram/axis/traits.hpp>
|
||||
#include <boost/histogram/detail/attribute.hpp>
|
||||
#include <boost/histogram/detail/axes.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/histogram/unsafe_access.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
/**
|
||||
Coverage mode of the indexed range generator.
|
||||
|
||||
Defines options for the iteration strategy.
|
||||
*/
|
||||
enum class coverage {
|
||||
inner, /*!< iterate over inner bins, exclude underflow and overflow */
|
||||
all, /*!< iterate over all bins, including underflow and overflow */
|
||||
};
|
||||
|
||||
/// Range over histogram bins with multi-dimensional index.
|
||||
template <class Histogram>
|
||||
class BOOST_HISTOGRAM_DETAIL_NODISCARD indexed_range {
|
||||
using max_dim = mp11::mp_size_t<
|
||||
detail::buffer_size<typename detail::remove_cvref_t<Histogram>::axes_type>::value>;
|
||||
using value_iterator = decltype(std::declval<Histogram>().begin());
|
||||
struct cache_item {
|
||||
int idx, begin, end, extent;
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
Pointer-like class to access value and index of current cell.
|
||||
|
||||
Its methods allow one to query the current indices and bins. Furthermore, it acts like
|
||||
a pointer to the cell value.
|
||||
*/
|
||||
class accessor {
|
||||
public:
|
||||
/// Array-like view into the current multi-dimensional index.
|
||||
class index_view {
|
||||
public:
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
class index_iterator
|
||||
: public boost::iterator_adaptor<index_iterator, const cache_item*> {
|
||||
public:
|
||||
index_iterator(const cache_item* i) : index_iterator::iterator_adaptor_(i) {}
|
||||
decltype(auto) operator*() const noexcept { return index_iterator::base()->idx; }
|
||||
};
|
||||
#endif
|
||||
|
||||
auto begin() const noexcept { return index_iterator(begin_); }
|
||||
auto end() const noexcept { return index_iterator(end_); }
|
||||
auto size() const noexcept { return static_cast<std::size_t>(end_ - begin_); }
|
||||
int operator[](unsigned d) const noexcept { return begin_[d].idx; }
|
||||
int at(unsigned d) const { return begin_[d].idx; }
|
||||
|
||||
private:
|
||||
index_view(const cache_item* b, const cache_item* e) : begin_(b), end_(e) {}
|
||||
const cache_item *begin_, *end_;
|
||||
friend class accessor;
|
||||
};
|
||||
|
||||
/// Returns the cell value.
|
||||
decltype(auto) operator*() const noexcept { return *iter_; }
|
||||
/// Returns the cell value.
|
||||
decltype(auto) get() const noexcept { return *iter_; }
|
||||
/// Access fields and methods of the cell object.
|
||||
decltype(auto) operator-> () const noexcept { return iter_; }
|
||||
|
||||
/// Access current index.
|
||||
/// @param d axis dimension.
|
||||
int index(unsigned d = 0) const noexcept { return parent_.cache_[d].idx; }
|
||||
|
||||
/// Access indices as an iterable range.
|
||||
auto indices() const noexcept {
|
||||
return index_view(parent_.cache_, parent_.cache_ + parent_.hist_.rank());
|
||||
}
|
||||
|
||||
/// Access current bin.
|
||||
/// @tparam N axis dimension.
|
||||
template <unsigned N = 0>
|
||||
decltype(auto) bin(std::integral_constant<unsigned, N> = {}) const {
|
||||
return parent_.hist_.axis(std::integral_constant<unsigned, N>()).bin(index(N));
|
||||
}
|
||||
|
||||
/// Access current bin.
|
||||
/// @param d axis dimension.
|
||||
decltype(auto) bin(unsigned d) const { return parent_.hist_.axis(d).bin(index(d)); }
|
||||
|
||||
/**
|
||||
Computes density in current cell.
|
||||
|
||||
The density is computed as the cell value divided by the product of bin widths. Axes
|
||||
without bin widths, like axis::category, are treated as having unit bin with.
|
||||
*/
|
||||
double density() const {
|
||||
double x = 1;
|
||||
auto it = parent_.cache_;
|
||||
parent_.hist_.for_each_axis([&](const auto& a) {
|
||||
const auto w = axis::traits::width_as<double>(a, it++->idx);
|
||||
x *= w ? w : 1;
|
||||
});
|
||||
return *iter_ / x;
|
||||
}
|
||||
|
||||
private:
|
||||
accessor(indexed_range& p, value_iterator i) : parent_(p), iter_(i) {}
|
||||
indexed_range& parent_;
|
||||
value_iterator iter_;
|
||||
friend class indexed_range;
|
||||
};
|
||||
|
||||
class range_iterator
|
||||
: public boost::iterator_adaptor<range_iterator, value_iterator, accessor,
|
||||
std::forward_iterator_tag, accessor> {
|
||||
public:
|
||||
accessor operator*() const noexcept { return {*parent_, range_iterator::base()}; }
|
||||
|
||||
private:
|
||||
range_iterator(indexed_range* p, value_iterator i) noexcept
|
||||
: range_iterator::iterator_adaptor_(i), parent_(p) {}
|
||||
|
||||
void increment() noexcept {
|
||||
std::size_t stride = 1;
|
||||
auto c = parent_->cache_;
|
||||
++c->idx;
|
||||
++range_iterator::base_reference();
|
||||
while (c->idx == c->end && (c != (parent_->cache_ + parent_->hist_.rank() - 1))) {
|
||||
c->idx = c->begin;
|
||||
range_iterator::base_reference() -= (c->end - c->begin) * stride;
|
||||
stride *= c->extent;
|
||||
++c;
|
||||
++c->idx;
|
||||
range_iterator::base_reference() += stride;
|
||||
}
|
||||
}
|
||||
|
||||
mutable indexed_range* parent_;
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
friend class indexed_range;
|
||||
};
|
||||
|
||||
indexed_range(Histogram& h, coverage c)
|
||||
: hist_(h), cover_all_(c == coverage::all), begin_(hist_.begin()), end_(begin_) {
|
||||
auto ca = cache_;
|
||||
const auto clast = ca + hist_.rank() - 1;
|
||||
std::size_t stride = 1;
|
||||
h.for_each_axis([&, this](const auto& a) {
|
||||
using opt = axis::traits::static_options<decltype(a)>;
|
||||
constexpr int under = opt::test(axis::option::underflow);
|
||||
constexpr int over = opt::test(axis::option::overflow);
|
||||
const auto size = a.size();
|
||||
|
||||
ca->extent = size + under + over;
|
||||
// -1 if underflow and cover all, else 0
|
||||
ca->begin = cover_all_ ? -under : 0;
|
||||
// size + 1 if overflow and cover all, else size
|
||||
ca->end = cover_all_ ? size + over : size;
|
||||
ca->idx = ca->begin;
|
||||
|
||||
begin_ += (ca->begin + under) * stride;
|
||||
if (ca < clast)
|
||||
end_ += (ca->begin + under) * stride;
|
||||
else
|
||||
end_ += (ca->end + under) * stride;
|
||||
|
||||
stride *= ca->extent;
|
||||
++ca;
|
||||
});
|
||||
}
|
||||
|
||||
range_iterator begin() noexcept { return {this, begin_}; }
|
||||
range_iterator end() noexcept { return {nullptr, end_}; }
|
||||
|
||||
private:
|
||||
Histogram& hist_;
|
||||
const bool cover_all_;
|
||||
value_iterator begin_, end_;
|
||||
mutable cache_item cache_[max_dim::value];
|
||||
};
|
||||
|
||||
/**
|
||||
Generates a range over the histogram entries.
|
||||
|
||||
Use this in a range-based for loop:
|
||||
|
||||
```
|
||||
for (auto x : indexed(hist)) { ... }
|
||||
```
|
||||
|
||||
The iterators dereference to an indexed_range::accessor, which has methods to query the
|
||||
current indices and bins, and acts like a pointer to the cell value.
|
||||
|
||||
@param hist Reference to the histogram.
|
||||
@param cov Iterate over all or only inner bins (optional, default: inner).
|
||||
*/
|
||||
template <typename Histogram>
|
||||
auto indexed(Histogram&& hist, coverage cov = coverage::inner) {
|
||||
return indexed_range<std::remove_reference_t<Histogram>>{std::forward<Histogram>(hist),
|
||||
cov};
|
||||
}
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
33
macx64/include/boost/histogram/literals.hpp
Normal file
33
macx64/include/boost/histogram/literals.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_LITERALS_HPP
|
||||
#define BOOST_HISTOGRAM_LITERALS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
constexpr unsigned parse_number(unsigned n) { return n; }
|
||||
|
||||
template <class... Rest>
|
||||
constexpr unsigned parse_number(unsigned n, char f, Rest... rest) {
|
||||
return parse_number(10u * n + static_cast<unsigned>(f - '0'), rest...);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
namespace literals {
|
||||
/// Suffix operator to generate literal compile-time numbers, 0_c, 12_c, etc.
|
||||
template <char... digits>
|
||||
auto operator"" _c() {
|
||||
return std::integral_constant<unsigned, detail::parse_number(0, digits...)>();
|
||||
}
|
||||
} // namespace literals
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
133
macx64/include/boost/histogram/make_histogram.hpp
Normal file
133
macx64/include/boost/histogram/make_histogram.hpp
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2015-2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_MAKE_HISTOGRAM_HPP
|
||||
#define BOOST_HISTOGRAM_MAKE_HISTOGRAM_HPP
|
||||
|
||||
/**
|
||||
\file boost/histogram/make_histogram.hpp
|
||||
Collection of factory functions to conveniently create histograms.
|
||||
*/
|
||||
|
||||
#include <boost/histogram/accumulators/weighted_sum.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/histogram.hpp>
|
||||
#include <boost/histogram/storage_adaptor.hpp>
|
||||
#include <boost/histogram/unlimited_storage.hpp> // = default_storage
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
/**
|
||||
Make histogram from compile-time axis configuration and custom storage.
|
||||
@param storage Storage or container with standard interface (any vector, array, or map).
|
||||
@param axis First axis instance.
|
||||
@param axes Other axis instances.
|
||||
*/
|
||||
template <class Storage, class Axis, class... Axes, class = detail::requires_axis<Axis>>
|
||||
auto make_histogram_with(Storage&& storage, Axis&& axis, Axes&&... axes) {
|
||||
auto a = std::make_tuple(std::forward<Axis>(axis), std::forward<Axes>(axes)...);
|
||||
using U = detail::remove_cvref_t<Storage>;
|
||||
using S = mp11::mp_if<detail::is_storage<U>, U, storage_adaptor<U>>;
|
||||
return histogram<decltype(a), S>(std::move(a), S(std::forward<Storage>(storage)));
|
||||
}
|
||||
|
||||
/**
|
||||
Make histogram from compile-time axis configuration and default storage.
|
||||
@param axis First axis instance.
|
||||
@param axes Other axis instances.
|
||||
*/
|
||||
template <class Axis, class... Axes, class = detail::requires_axis<Axis>>
|
||||
auto make_histogram(Axis&& axis, Axes&&... axes) {
|
||||
return make_histogram_with(default_storage(), std::forward<Axis>(axis),
|
||||
std::forward<Axes>(axes)...);
|
||||
}
|
||||
|
||||
/**
|
||||
Make histogram from compile-time axis configuration and weight-counting storage.
|
||||
@param axis First axis instance.
|
||||
@param axes Other axis instances.
|
||||
*/
|
||||
template <class Axis, class... Axes, class = detail::requires_axis<Axis>>
|
||||
auto make_weighted_histogram(Axis&& axis, Axes&&... axes) {
|
||||
return make_histogram_with(weight_storage(), std::forward<Axis>(axis),
|
||||
std::forward<Axes>(axes)...);
|
||||
}
|
||||
|
||||
/**
|
||||
Make histogram from iterable range and custom storage.
|
||||
@param storage Storage or container with standard interface (any vector, array, or map).
|
||||
@param iterable Iterable range of axis objects.
|
||||
*/
|
||||
template <class Storage, class Iterable,
|
||||
class = detail::requires_sequence_of_any_axis<Iterable>>
|
||||
auto make_histogram_with(Storage&& storage, Iterable&& iterable) {
|
||||
using U = detail::remove_cvref_t<Storage>;
|
||||
using S = mp11::mp_if<detail::is_storage<U>, U, storage_adaptor<U>>;
|
||||
using It = detail::remove_cvref_t<Iterable>;
|
||||
using A = mp11::mp_if<detail::is_indexable_container<It>, It,
|
||||
std::vector<mp11::mp_first<It>>>;
|
||||
return histogram<A, S>(std::forward<Iterable>(iterable),
|
||||
S(std::forward<Storage>(storage)));
|
||||
}
|
||||
|
||||
/**
|
||||
Make histogram from iterable range and default storage.
|
||||
@param iterable Iterable range of axis objects.
|
||||
*/
|
||||
template <class Iterable, class = detail::requires_sequence_of_any_axis<Iterable>>
|
||||
auto make_histogram(Iterable&& iterable) {
|
||||
return make_histogram_with(default_storage(), std::forward<Iterable>(iterable));
|
||||
}
|
||||
|
||||
/**
|
||||
Make histogram from iterable range and weight-counting storage.
|
||||
@param iterable Iterable range of axis objects.
|
||||
*/
|
||||
template <class Iterable, class = detail::requires_sequence_of_any_axis<Iterable>>
|
||||
auto make_weighted_histogram(Iterable&& iterable) {
|
||||
return make_histogram_with(weight_storage(), std::forward<Iterable>(iterable));
|
||||
}
|
||||
|
||||
/**
|
||||
Make histogram from iterator interval and custom storage.
|
||||
@param storage Storage or container with standard interface (any vector, array, or map).
|
||||
@param begin Iterator to range of axis objects.
|
||||
@param end Iterator to range of axis objects.
|
||||
*/
|
||||
template <class Storage, class Iterator, class = detail::requires_iterator<Iterator>>
|
||||
auto make_histogram_with(Storage&& storage, Iterator begin, Iterator end) {
|
||||
using T = detail::remove_cvref_t<decltype(*begin)>;
|
||||
return make_histogram_with(std::forward<Storage>(storage), std::vector<T>(begin, end));
|
||||
}
|
||||
|
||||
/**
|
||||
Make histogram from iterator interval and default storage.
|
||||
@param begin Iterator to range of axis objects.
|
||||
@param end Iterator to range of axis objects.
|
||||
*/
|
||||
template <class Iterator, class = detail::requires_iterator<Iterator>>
|
||||
auto make_histogram(Iterator begin, Iterator end) {
|
||||
return make_histogram_with(default_storage(), begin, end);
|
||||
}
|
||||
|
||||
/**
|
||||
Make histogram from iterator interval and weight-counting storage.
|
||||
@param begin Iterator to range of axis objects.
|
||||
@param end Iterator to range of axis objects.
|
||||
*/
|
||||
template <class Iterator, class = detail::requires_iterator<Iterator>>
|
||||
auto make_weighted_histogram(Iterator begin, Iterator end) {
|
||||
return make_histogram_with(weight_storage(), begin, end);
|
||||
}
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
90
macx64/include/boost/histogram/make_profile.hpp
Normal file
90
macx64/include/boost/histogram/make_profile.hpp
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_MAKE_PROFILE_HPP
|
||||
#define BOOST_HISTOGRAM_MAKE_PROFILE_HPP
|
||||
|
||||
#include <boost/histogram/accumulators/mean.hpp>
|
||||
#include <boost/histogram/accumulators/weighted_mean.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/histogram/make_histogram.hpp>
|
||||
|
||||
/**
|
||||
\file boost/histogram/make_profile.hpp
|
||||
Collection of factory functions to conveniently create profiles.
|
||||
|
||||
Profiles are histograms which accept an additional sample and compute the mean of the
|
||||
sample in each cell.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
/**
|
||||
Make profle from compile-time axis configuration.
|
||||
@param axis First axis instance.
|
||||
@param axes Other axis instances.
|
||||
*/
|
||||
template <typename Axis, typename... Axes, typename = detail::requires_axis<Axis>>
|
||||
auto make_profile(Axis&& axis, Axes&&... axes) {
|
||||
return make_histogram_with(profile_storage(), std::forward<Axis>(axis),
|
||||
std::forward<Axes>(axes)...);
|
||||
}
|
||||
|
||||
/**
|
||||
Make profle from compile-time axis configuration which accepts weights.
|
||||
@param axis First axis instance.
|
||||
@param axes Other axis instances.
|
||||
*/
|
||||
template <typename Axis, typename... Axes, typename = detail::requires_axis<Axis>>
|
||||
auto make_weighted_profile(Axis&& axis, Axes&&... axes) {
|
||||
return make_histogram_with(weighted_profile_storage(), std::forward<Axis>(axis),
|
||||
std::forward<Axes>(axes)...);
|
||||
}
|
||||
|
||||
/**
|
||||
Make profile from iterable range.
|
||||
@param iterable Iterable range of axis objects.
|
||||
*/
|
||||
template <typename Iterable, typename = detail::requires_sequence_of_any_axis<Iterable>>
|
||||
auto make_profile(Iterable&& iterable) {
|
||||
return make_histogram_with(profile_storage(), std::forward<Iterable>(iterable));
|
||||
}
|
||||
|
||||
/**
|
||||
Make profile from iterable range which accepts weights.
|
||||
@param iterable Iterable range of axis objects.
|
||||
*/
|
||||
template <typename Iterable, typename = detail::requires_sequence_of_any_axis<Iterable>>
|
||||
auto make_weighted_profile(Iterable&& iterable) {
|
||||
return make_histogram_with(weighted_profile_storage(),
|
||||
std::forward<Iterable>(iterable));
|
||||
}
|
||||
|
||||
/**
|
||||
Make profile from iterator interval.
|
||||
@param begin Iterator to range of axis objects.
|
||||
@param end Iterator to range of axis objects.
|
||||
*/
|
||||
template <typename Iterator, typename = detail::requires_iterator<Iterator>>
|
||||
auto make_profile(Iterator begin, Iterator end) {
|
||||
return make_histogram_with(profile_storage(), begin, end);
|
||||
}
|
||||
|
||||
/**
|
||||
Make profile from iterator interval which accepts weights.
|
||||
@param begin Iterator to range of axis objects.
|
||||
@param end Iterator to range of axis objects.
|
||||
*/
|
||||
template <typename Iterator, typename = detail::requires_iterator<Iterator>>
|
||||
auto make_weighted_profile(Iterator begin, Iterator end) {
|
||||
return make_histogram_with(weighted_profile_storage(), begin, end);
|
||||
}
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
39
macx64/include/boost/histogram/ostream.hpp
Normal file
39
macx64/include/boost/histogram/ostream.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_OSTREAM_HPP
|
||||
#define BOOST_HISTOGRAM_OSTREAM_HPP
|
||||
|
||||
#include <boost/histogram/accumulators/ostream.hpp>
|
||||
#include <boost/histogram/axis/ostream.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <iosfwd>
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
template <typename CharT, typename Traits, typename A, typename S>
|
||||
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
|
||||
const histogram<A, S>& h) {
|
||||
os << "histogram(";
|
||||
unsigned n = 0;
|
||||
h.for_each_axis([&](const auto& a) {
|
||||
if (h.rank() > 1) os << "\n ";
|
||||
os << a;
|
||||
if (++n < h.rank()) os << ",";
|
||||
});
|
||||
os << (h.rank() > 1 ? "\n)" : ")");
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
#endif
|
||||
214
macx64/include/boost/histogram/serialization.hpp
Normal file
214
macx64/include/boost/histogram/serialization.hpp
Normal file
@@ -0,0 +1,214 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_SERIALIZATION_HPP
|
||||
#define BOOST_HISTOGRAM_SERIALIZATION_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/accumulators/mean.hpp>
|
||||
#include <boost/histogram/accumulators/sum.hpp>
|
||||
#include <boost/histogram/accumulators/weighted_mean.hpp>
|
||||
#include <boost/histogram/accumulators/weighted_sum.hpp>
|
||||
#include <boost/histogram/axis/category.hpp>
|
||||
#include <boost/histogram/axis/integer.hpp>
|
||||
#include <boost/histogram/axis/regular.hpp>
|
||||
#include <boost/histogram/axis/variable.hpp>
|
||||
#include <boost/histogram/axis/variant.hpp>
|
||||
#include <boost/histogram/histogram.hpp>
|
||||
#include <boost/histogram/storage_adaptor.hpp>
|
||||
#include <boost/histogram/unlimited_storage.hpp>
|
||||
#include <boost/histogram/unsafe_access.hpp>
|
||||
#include <boost/mp11/tuple.hpp>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include <boost/serialization/map.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include <boost/serialization/variant.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
\file boost/histogram/serialization.hpp
|
||||
|
||||
Implemenations of the serialization functions using
|
||||
[Boost.Serialization](https://www.boost.org/doc/libs/develop/libs/serialization/doc/index.html).
|
||||
*/
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
namespace std {
|
||||
template <class Archive, class... Ts>
|
||||
void serialize(Archive& ar, tuple<Ts...>& t, unsigned /* version */) {
|
||||
::boost::mp11::tuple_for_each(
|
||||
t, [&ar](auto& x) { ar& boost::serialization::make_nvp("item", x); });
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
namespace accumulators {
|
||||
template <class RealType>
|
||||
template <class Archive>
|
||||
void sum<RealType>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("large", large_);
|
||||
ar& serialization::make_nvp("small", small_);
|
||||
}
|
||||
|
||||
template <class RealType>
|
||||
template <class Archive>
|
||||
void weighted_sum<RealType>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("sum_of_weights", sum_of_weights_);
|
||||
ar& serialization::make_nvp("sum_of_weights_squared", sum_of_weights_squared_);
|
||||
}
|
||||
|
||||
template <class RealType>
|
||||
template <class Archive>
|
||||
void mean<RealType>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("sum", sum_);
|
||||
ar& serialization::make_nvp("mean", mean_);
|
||||
ar& serialization::make_nvp("sum_of_deltas_squared", sum_of_deltas_squared_);
|
||||
}
|
||||
|
||||
template <class RealType>
|
||||
template <class Archive>
|
||||
void weighted_mean<RealType>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("sum_of_weights", sum_of_weights_);
|
||||
ar& serialization::make_nvp("sum_of_weights_squared", sum_of_weights_squared_);
|
||||
ar& serialization::make_nvp("weighted_mean", weighted_mean_);
|
||||
ar& serialization::make_nvp("sum_of_weighted_deltas_squared",
|
||||
sum_of_weighted_deltas_squared_);
|
||||
}
|
||||
} // namespace accumulators
|
||||
|
||||
namespace axis {
|
||||
|
||||
namespace transform {
|
||||
template <class Archive>
|
||||
void serialize(Archive&, id&, unsigned /* version */) {}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, log&, unsigned /* version */) {}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, sqrt&, unsigned /* version */) {}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, pow& t, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("power", t.power);
|
||||
}
|
||||
} // namespace transform
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, null_type&, unsigned /* version */) {}
|
||||
|
||||
template <class T, class Tr, class M, class O>
|
||||
template <class Archive>
|
||||
void regular<T, Tr, M, O>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("transform", static_cast<transform_type&>(*this));
|
||||
ar& serialization::make_nvp("size", size_meta_.first());
|
||||
ar& serialization::make_nvp("meta", size_meta_.second());
|
||||
ar& serialization::make_nvp("min", min_);
|
||||
ar& serialization::make_nvp("delta", delta_);
|
||||
}
|
||||
|
||||
template <class T, class M, class O>
|
||||
template <class Archive>
|
||||
void integer<T, M, O>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("size", size_meta_.first());
|
||||
ar& serialization::make_nvp("meta", size_meta_.second());
|
||||
ar& serialization::make_nvp("min", min_);
|
||||
}
|
||||
|
||||
template <class T, class M, class O, class A>
|
||||
template <class Archive>
|
||||
void variable<T, M, O, A>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("seq", vec_meta_.first());
|
||||
ar& serialization::make_nvp("meta", vec_meta_.second());
|
||||
}
|
||||
|
||||
template <class T, class M, class O, class A>
|
||||
template <class Archive>
|
||||
void category<T, M, O, A>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("seq", vec_meta_.first());
|
||||
ar& serialization::make_nvp("meta", vec_meta_.second());
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
template <class Archive>
|
||||
void variant<Ts...>::serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("variant", impl);
|
||||
}
|
||||
} // namespace axis
|
||||
|
||||
namespace detail {
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, vector_impl<T>& impl, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("vector", static_cast<T&>(impl));
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, array_impl<T>& impl, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("size", impl.size_);
|
||||
ar& serialization::make_nvp("array",
|
||||
serialization::make_array(&impl.front(), impl.size_));
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, map_impl<T>& impl, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("size", impl.size_);
|
||||
ar& serialization::make_nvp("map", static_cast<T&>(impl));
|
||||
}
|
||||
|
||||
template <class Archive, class Allocator>
|
||||
void serialize(Archive& ar, mp_int<Allocator>& x, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("data", x.data);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, storage_adaptor<T>& s, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("impl", static_cast<detail::storage_adaptor_impl<T>&>(s));
|
||||
}
|
||||
|
||||
template <class A>
|
||||
template <class Archive>
|
||||
void unlimited_storage<A>::serialize(Archive& ar, unsigned /* version */) {
|
||||
if (Archive::is_loading::value) {
|
||||
buffer_type dummy(buffer.alloc);
|
||||
std::size_t size;
|
||||
ar& serialization::make_nvp("type", dummy.type);
|
||||
ar& serialization::make_nvp("size", size);
|
||||
dummy.apply([this, size](auto* tp) {
|
||||
BOOST_ASSERT(tp == nullptr);
|
||||
using T = detail::remove_cvref_t<decltype(*tp)>;
|
||||
buffer.template make<T>(size);
|
||||
});
|
||||
} else {
|
||||
ar& serialization::make_nvp("type", buffer.type);
|
||||
ar& serialization::make_nvp("size", buffer.size);
|
||||
}
|
||||
buffer.apply([this, &ar](auto* tp) {
|
||||
using T = detail::remove_cvref_t<decltype(*tp)>;
|
||||
ar& serialization::make_nvp(
|
||||
"buffer",
|
||||
serialization::make_array(reinterpret_cast<T*>(buffer.ptr), buffer.size));
|
||||
});
|
||||
}
|
||||
|
||||
template <class Archive, class A, class S>
|
||||
void serialize(Archive& ar, histogram<A, S>& h, unsigned /* version */) {
|
||||
ar& serialization::make_nvp("axes", unsafe_access::axes(h));
|
||||
ar& serialization::make_nvp("storage", unsafe_access::storage(h));
|
||||
}
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
298
macx64/include/boost/histogram/storage_adaptor.hpp
Normal file
298
macx64/include/boost/histogram/storage_adaptor.hpp
Normal file
@@ -0,0 +1,298 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_STORAGE_ADAPTOR_HPP
|
||||
#define BOOST_HISTOGRAM_STORAGE_ADAPTOR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/detail/cat.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
struct vector_impl : T {
|
||||
vector_impl() = default;
|
||||
|
||||
explicit vector_impl(const T& t) : T(t) {}
|
||||
explicit vector_impl(typename T::allocator_type a) : T(a) {}
|
||||
|
||||
template <class U, class = requires_iterable<U>>
|
||||
explicit vector_impl(const U& u) {
|
||||
T::reserve(u.size());
|
||||
for (auto&& x : u) T::emplace_back(x);
|
||||
}
|
||||
|
||||
template <class U, class = requires_iterable<U>>
|
||||
vector_impl& operator=(const U& u) {
|
||||
T::resize(u.size());
|
||||
auto it = T::begin();
|
||||
for (auto&& x : u) *it++ = x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset(std::size_t n) {
|
||||
using value_type = typename T::value_type;
|
||||
const auto old_size = T::size();
|
||||
T::resize(n, value_type());
|
||||
std::fill_n(T::begin(), std::min(n, old_size), value_type());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct array_impl : T {
|
||||
array_impl() = default;
|
||||
|
||||
explicit array_impl(const T& t) : T(t) {}
|
||||
template <class U, class = requires_iterable<U>>
|
||||
explicit array_impl(const U& u) : size_(u.size()) {
|
||||
std::size_t i = 0;
|
||||
for (auto&& x : u) T::operator[](i++) = x;
|
||||
}
|
||||
|
||||
template <class U, class = requires_iterable<U>>
|
||||
array_impl& operator=(const U& u) {
|
||||
size_ = u.size();
|
||||
if (size_ > T::max_size()) // for std::array
|
||||
BOOST_THROW_EXCEPTION(std::length_error(
|
||||
detail::cat("size ", size_, " exceeds maximum capacity ", T::max_size())));
|
||||
auto it = T::begin();
|
||||
for (auto&& x : u) *it++ = x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset(std::size_t n) {
|
||||
using value_type = typename T::value_type;
|
||||
if (n > T::max_size()) // for std::array
|
||||
BOOST_THROW_EXCEPTION(std::length_error(
|
||||
detail::cat("size ", n, " exceeds maximum capacity ", T::max_size())));
|
||||
std::fill_n(T::begin(), n, value_type());
|
||||
size_ = n;
|
||||
}
|
||||
|
||||
typename T::iterator end() noexcept { return T::begin() + size_; }
|
||||
typename T::const_iterator end() const noexcept { return T::begin() + size_; }
|
||||
|
||||
std::size_t size() const noexcept { return size_; }
|
||||
|
||||
std::size_t size_ = 0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct map_impl : T {
|
||||
static_assert(std::is_same<typename T::key_type, std::size_t>::value,
|
||||
"requires std::size_t as key_type");
|
||||
|
||||
using value_type = typename T::mapped_type;
|
||||
using const_reference = const value_type&;
|
||||
|
||||
struct reference {
|
||||
reference(map_impl* m, std::size_t i) noexcept : map(m), idx(i) {}
|
||||
reference(const reference&) noexcept = default;
|
||||
reference operator=(reference o) {
|
||||
if (this != &o) operator=(static_cast<const_reference>(o));
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator const_reference() const noexcept {
|
||||
return static_cast<const map_impl*>(map)->operator[](idx);
|
||||
}
|
||||
|
||||
template <class U, class = requires_convertible<U, value_type>>
|
||||
reference& operator=(const U& u) {
|
||||
auto it = map->find(idx);
|
||||
if (u == value_type()) {
|
||||
if (it != static_cast<T*>(map)->end()) map->erase(it);
|
||||
} else {
|
||||
if (it != static_cast<T*>(map)->end())
|
||||
it->second = u;
|
||||
else {
|
||||
map->emplace(idx, u);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U, class V = value_type,
|
||||
class = std::enable_if_t<has_operator_radd<V, U>::value>>
|
||||
reference operator+=(const U& u) {
|
||||
auto it = map->find(idx);
|
||||
if (it != static_cast<T*>(map)->end())
|
||||
it->second += u;
|
||||
else
|
||||
map->emplace(idx, u);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U, class V = value_type,
|
||||
class = std::enable_if_t<has_operator_rsub<V, U>::value>>
|
||||
reference operator-=(const U& u) {
|
||||
auto it = map->find(idx);
|
||||
if (it != static_cast<T*>(map)->end())
|
||||
it->second -= u;
|
||||
else
|
||||
map->emplace(idx, -u);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U, class V = value_type,
|
||||
class = std::enable_if_t<has_operator_rmul<V, U>::value>>
|
||||
reference operator*=(const U& u) {
|
||||
auto it = map->find(idx);
|
||||
if (it != static_cast<T*>(map)->end()) it->second *= u;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U, class V = value_type,
|
||||
class = std::enable_if_t<has_operator_rdiv<V, U>::value>>
|
||||
reference operator/=(const U& u) {
|
||||
auto it = map->find(idx);
|
||||
if (it != static_cast<T*>(map)->end())
|
||||
it->second /= u;
|
||||
else if (!(value_type{} / u == value_type{}))
|
||||
map->emplace(idx, value_type{} / u);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class V = value_type,
|
||||
class = std::enable_if_t<has_operator_preincrement<V>::value>>
|
||||
reference operator++() {
|
||||
auto it = map->find(idx);
|
||||
if (it != static_cast<T*>(map)->end())
|
||||
++it->second;
|
||||
else
|
||||
map->emplace(idx, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class V = value_type,
|
||||
class = std::enable_if_t<has_operator_preincrement<V>::value>>
|
||||
value_type operator++(int) {
|
||||
const value_type tmp = operator const_reference();
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
decltype(auto) operator()(Ts&&... args) {
|
||||
return map->operator[](idx)(std::forward<Ts>(args)...);
|
||||
}
|
||||
|
||||
map_impl* map;
|
||||
std::size_t idx;
|
||||
};
|
||||
|
||||
template <class Value, class Reference, class MapPtr>
|
||||
struct iterator_t
|
||||
: boost::iterator_adaptor<iterator_t<Value, Reference, MapPtr>, std::size_t, Value,
|
||||
std::random_access_iterator_tag, Reference,
|
||||
std::ptrdiff_t> {
|
||||
iterator_t() = default;
|
||||
template <class V, class R, class M, class = requires_convertible<M, MapPtr>>
|
||||
iterator_t(const iterator_t<V, R, M>& it) noexcept : iterator_t(it.map_, it.base()) {}
|
||||
iterator_t(MapPtr m, std::size_t i) noexcept
|
||||
: iterator_t::iterator_adaptor_(i), map_(m) {}
|
||||
template <class V, class R, class M>
|
||||
bool equal(const iterator_t<V, R, M>& rhs) const noexcept {
|
||||
return map_ == rhs.map_ && iterator_t::base() == rhs.base();
|
||||
}
|
||||
decltype(auto) dereference() const { return (*map_)[iterator_t::base()]; }
|
||||
MapPtr map_ = nullptr;
|
||||
};
|
||||
|
||||
using iterator = iterator_t<value_type, reference, map_impl*>;
|
||||
using const_iterator = iterator_t<const value_type, const_reference, const map_impl*>;
|
||||
|
||||
map_impl() = default;
|
||||
|
||||
explicit map_impl(const T& t) : T(t) {}
|
||||
explicit map_impl(typename T::allocator_type a) : T(a) {}
|
||||
|
||||
template <class U, class = requires_iterable<U>>
|
||||
explicit map_impl(const U& u) : size_(u.size()) {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
std::copy(begin(u), end(u), this->begin());
|
||||
}
|
||||
|
||||
template <class U, class = requires_iterable<U>>
|
||||
map_impl& operator=(const U& u) {
|
||||
if (u.size() < size_)
|
||||
reset(u.size());
|
||||
else
|
||||
size_ = u.size();
|
||||
using std::begin;
|
||||
using std::end;
|
||||
std::copy(begin(u), end(u), this->begin());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset(std::size_t n) {
|
||||
T::clear();
|
||||
size_ = n;
|
||||
}
|
||||
|
||||
reference operator[](std::size_t i) noexcept { return {this, i}; }
|
||||
const_reference operator[](std::size_t i) const noexcept {
|
||||
auto it = T::find(i);
|
||||
static const value_type null = value_type{};
|
||||
if (it == T::end()) return null;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
iterator begin() noexcept { return {this, 0}; }
|
||||
iterator end() noexcept { return {this, size_}; }
|
||||
|
||||
const_iterator begin() const noexcept { return {this, 0}; }
|
||||
const_iterator end() const noexcept { return {this, size_}; }
|
||||
|
||||
std::size_t size() const noexcept { return size_; }
|
||||
|
||||
std::size_t size_ = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ERROR_type_passed_to_storage_adaptor_not_recognized;
|
||||
|
||||
template <typename T>
|
||||
using storage_adaptor_impl = mp11::mp_if<
|
||||
is_vector_like<T>, vector_impl<T>,
|
||||
mp11::mp_if<is_array_like<T>, array_impl<T>,
|
||||
mp11::mp_if<is_map_like<T>, map_impl<T>,
|
||||
ERROR_type_passed_to_storage_adaptor_not_recognized<T>>>>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Turns any vector-like array-like, and map-like container into a storage type.
|
||||
template <typename T>
|
||||
class storage_adaptor : public detail::storage_adaptor_impl<T> {
|
||||
using base_type = detail::storage_adaptor_impl<T>;
|
||||
|
||||
public:
|
||||
using base_type::base_type;
|
||||
using base_type::operator=;
|
||||
|
||||
template <class U, class = detail::requires_iterable<U>>
|
||||
bool operator==(const U& u) const {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
return std::equal(this->begin(), this->end(), begin(u), end(u));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
923
macx64/include/boost/histogram/unlimited_storage.hpp
Normal file
923
macx64/include/boost/histogram/unlimited_storage.hpp
Normal file
@@ -0,0 +1,923 @@
|
||||
// Copyright 2015-2017 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_UNLIMTED_STORAGE_HPP
|
||||
#define BOOST_HISTOGRAM_UNLIMTED_STORAGE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// version of std::equal_to<> which handles comparison of signed and unsigned
|
||||
struct equal {
|
||||
template <class T, class U>
|
||||
bool operator()(const T& t, const U& u) const noexcept {
|
||||
return impl(std::is_signed<T>{}, std::is_signed<U>{}, t, u);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::false_type, std::false_type, const T& t, const U& u) const noexcept {
|
||||
return t == u;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::false_type, std::true_type, const T& t, const U& u) const noexcept {
|
||||
return u >= 0 && t == make_unsigned(u);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::true_type, std::false_type, const T& t, const U& u) const noexcept {
|
||||
return t >= 0 && make_unsigned(t) == u;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::true_type, std::true_type, const T& t, const U& u) const noexcept {
|
||||
return t == u;
|
||||
}
|
||||
};
|
||||
|
||||
// version of std::less<> which handles comparison of signed and unsigned
|
||||
struct less {
|
||||
template <class T, class U>
|
||||
bool operator()(const T& t, const U& u) const noexcept {
|
||||
return impl(std::is_signed<T>{}, std::is_signed<U>{}, t, u);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::false_type, std::false_type, const T& t, const U& u) const noexcept {
|
||||
return t < u;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::false_type, std::true_type, const T& t, const U& u) const noexcept {
|
||||
return u >= 0 && t < make_unsigned(u);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::true_type, std::false_type, const T& t, const U& u) const noexcept {
|
||||
return t < 0 || make_unsigned(t) < u;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::true_type, std::true_type, const T& t, const U& u) const noexcept {
|
||||
return t < u;
|
||||
}
|
||||
};
|
||||
|
||||
// version of std::greater<> which handles comparison of signed and unsigned
|
||||
struct greater {
|
||||
template <class T, class U>
|
||||
bool operator()(const T& t, const U& u) const noexcept {
|
||||
return impl(std::is_signed<T>{}, std::is_signed<U>{}, t, u);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::false_type, std::false_type, const T& t, const U& u) const noexcept {
|
||||
return t > u;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::false_type, std::true_type, const T& t, const U& u) const noexcept {
|
||||
return u < 0 || t > make_unsigned(u);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::true_type, std::false_type, const T& t, const U& u) const noexcept {
|
||||
return t >= 0 && make_unsigned(t) > u;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool impl(std::true_type, std::true_type, const T& t, const U& u) const noexcept {
|
||||
return t > u;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
struct mp_int;
|
||||
|
||||
template <class T>
|
||||
struct is_unsigned_integral : mp11::mp_and<std::is_integral<T>, std::is_unsigned<T>> {};
|
||||
|
||||
template <class T>
|
||||
bool safe_increment(T& t) {
|
||||
if (t < std::numeric_limits<T>::max()) {
|
||||
++t;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool safe_radd(T& t, const U& u) {
|
||||
static_assert(is_unsigned_integral<T>::value, "T must be unsigned integral type");
|
||||
static_assert(is_unsigned_integral<U>::value, "T must be unsigned integral type");
|
||||
if (static_cast<T>(std::numeric_limits<T>::max() - t) >= u) {
|
||||
t += static_cast<T>(u); // static_cast to suppress conversion warning
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// use boost.multiprecision.cpp_int in your own code, it is much more sophisticated
|
||||
// than this implementation; we use it here to reduce coupling between boost libs
|
||||
template <class Allocator>
|
||||
struct mp_int {
|
||||
explicit mp_int(Allocator a = {}) : data(1, 0, std::move(a)) {}
|
||||
explicit mp_int(uint64_t v, Allocator a = {}) : data(1, v, std::move(a)) {}
|
||||
mp_int(const mp_int&) = default;
|
||||
mp_int& operator=(const mp_int&) = default;
|
||||
mp_int(mp_int&&) = default;
|
||||
mp_int& operator=(mp_int&&) = default;
|
||||
|
||||
mp_int& operator=(uint64_t o) {
|
||||
data = decltype(data)(1, o);
|
||||
return *this;
|
||||
}
|
||||
|
||||
mp_int& operator++() {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
std::size_t i = 0;
|
||||
while (!safe_increment(data[i])) {
|
||||
data[i] = 0;
|
||||
++i;
|
||||
if (i == data.size()) {
|
||||
data.push_back(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
mp_int& operator+=(const mp_int& o) {
|
||||
if (this == &o) {
|
||||
auto tmp{o};
|
||||
return operator+=(tmp);
|
||||
}
|
||||
bool carry = false;
|
||||
std::size_t i = 0;
|
||||
for (uint64_t oi : o.data) {
|
||||
auto& di = maybe_extend(i);
|
||||
if (carry) {
|
||||
if (safe_increment(oi))
|
||||
carry = false;
|
||||
else {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!safe_radd(di, oi)) {
|
||||
add_remainder(di, oi);
|
||||
carry = true;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
while (carry) {
|
||||
auto& di = maybe_extend(i);
|
||||
if (safe_increment(di)) break;
|
||||
di = 0;
|
||||
++i;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
mp_int& operator+=(uint64_t o) {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
if (safe_radd(data[0], o)) return *this;
|
||||
add_remainder(data[0], o);
|
||||
// carry the one, data may grow several times
|
||||
std::size_t i = 1;
|
||||
while (true) {
|
||||
auto& di = maybe_extend(i);
|
||||
if (safe_increment(di)) break;
|
||||
di = 0;
|
||||
++i;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator double() const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
double result = static_cast<double>(data[0]);
|
||||
std::size_t i = 0;
|
||||
while (++i < data.size())
|
||||
result += static_cast<double>(data[i]) * std::pow(2.0, i * 64);
|
||||
return result;
|
||||
}
|
||||
|
||||
// total ordering for mp_int, mp_int
|
||||
bool operator<(const mp_int& o) const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
BOOST_ASSERT(o.data.size() > 0u);
|
||||
// no leading zeros allowed
|
||||
BOOST_ASSERT(data.size() == 1 || data.back() > 0u);
|
||||
BOOST_ASSERT(o.data.size() == 1 || o.data.back() > 0u);
|
||||
if (data.size() < o.data.size()) return true;
|
||||
if (data.size() > o.data.size()) return false;
|
||||
auto s = data.size();
|
||||
while (s > 0u) {
|
||||
--s;
|
||||
if (data[s] < o.data[s]) return true;
|
||||
if (data[s] > o.data[s]) return false;
|
||||
}
|
||||
return false; // args are equal
|
||||
}
|
||||
|
||||
bool operator==(const mp_int& o) const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
BOOST_ASSERT(o.data.size() > 0u);
|
||||
// no leading zeros allowed
|
||||
BOOST_ASSERT(data.size() == 1 || data.back() > 0u);
|
||||
BOOST_ASSERT(o.data.size() == 1 || o.data.back() > 0u);
|
||||
if (data.size() != o.data.size()) return false;
|
||||
return std::equal(data.begin(), data.end(), o.data.begin());
|
||||
}
|
||||
|
||||
// copied from boost/operators.hpp
|
||||
friend bool operator>(const mp_int& x, const mp_int& y) { return y < x; }
|
||||
friend bool operator<=(const mp_int& x, const mp_int& y) { return !(y < x); }
|
||||
friend bool operator>=(const mp_int& x, const mp_int& y) { return !(x < y); }
|
||||
friend bool operator!=(const mp_int& x, const mp_int& y) { return !(x == y); }
|
||||
|
||||
// total ordering for mp_int, uint64; partial ordering for mp_int, double
|
||||
template <class U>
|
||||
bool operator<(const U& o) const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
return static_if<is_unsigned_integral<U>>(
|
||||
[this](uint64_t o) { return data.size() == 1 && data[0] < o; },
|
||||
[this](double o) { return operator double() < o; }, o);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
bool operator>(const U& o) const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
BOOST_ASSERT(data.back() > 0u); // no leading zeros allowed
|
||||
return static_if<is_unsigned_integral<U>>(
|
||||
[this](uint64_t o) { return data.size() > 1 || data[0] > o; },
|
||||
[this](double o) { return operator double() > o; }, o);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
bool operator==(const U& o) const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
return static_if<is_unsigned_integral<U>>(
|
||||
[this](uint64_t o) { return data.size() == 1 && data[0] == o; },
|
||||
[this](double o) { return operator double() == o; }, o);
|
||||
}
|
||||
|
||||
// adapted copy from boost/operators.hpp
|
||||
template <class U>
|
||||
friend bool operator<=(const mp_int& x, const U& y) {
|
||||
if (is_unsigned_integral<U>::value) return !(x > y);
|
||||
return (x < y) || (x == y);
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator>=(const mp_int& x, const U& y) {
|
||||
if (is_unsigned_integral<U>::value) return !(x < y);
|
||||
return (x > y) || (x == y);
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator>(const U& x, const mp_int& y) {
|
||||
if (is_unsigned_integral<U>::value) return y < x;
|
||||
return y < x;
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator<(const U& x, const mp_int& y) {
|
||||
if (is_unsigned_integral<U>::value) return y > x;
|
||||
return y > x;
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator<=(const U& x, const mp_int& y) {
|
||||
if (is_unsigned_integral<U>::value) return !(y < x);
|
||||
return (y > x) || (y == x);
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator>=(const U& x, const mp_int& y) {
|
||||
if (is_unsigned_integral<U>::value) return !(y > x);
|
||||
return (y < x) || (y == x);
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator==(const U& y, const mp_int& x) {
|
||||
return x == y;
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator!=(const U& y, const mp_int& x) {
|
||||
return !(x == y);
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator!=(const mp_int& y, const U& x) {
|
||||
return !(y == x);
|
||||
}
|
||||
|
||||
uint64_t& maybe_extend(std::size_t i) {
|
||||
while (i >= data.size()) data.push_back(0);
|
||||
return data[i];
|
||||
}
|
||||
|
||||
static void add_remainder(uint64_t& d, const uint64_t o) noexcept {
|
||||
BOOST_ASSERT(d > 0u);
|
||||
// in decimal system it would look like this:
|
||||
// 8 + 8 = 6 = 8 - (9 - 8) - 1
|
||||
// 9 + 1 = 0 = 9 - (9 - 1) - 1
|
||||
auto tmp = std::numeric_limits<uint64_t>::max();
|
||||
tmp -= o;
|
||||
--d -= tmp;
|
||||
}
|
||||
|
||||
std::vector<uint64_t, Allocator> data;
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
auto create_buffer(Allocator& a, std::size_t n) {
|
||||
using AT = std::allocator_traits<Allocator>;
|
||||
auto ptr = AT::allocate(a, n); // may throw
|
||||
static_assert(std::is_trivially_copyable<decltype(ptr)>::value,
|
||||
"ptr must be trivially copyable");
|
||||
auto it = ptr;
|
||||
const auto end = ptr + n;
|
||||
try {
|
||||
// this loop may throw
|
||||
while (it != end) AT::construct(a, it++, typename AT::value_type{});
|
||||
} catch (...) {
|
||||
// release resources that were already acquired before rethrowing
|
||||
while (it != ptr) AT::destroy(a, --it);
|
||||
AT::deallocate(a, ptr, n);
|
||||
throw;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class Allocator, class Iterator>
|
||||
auto create_buffer(Allocator& a, std::size_t n, Iterator iter) {
|
||||
BOOST_ASSERT(n > 0u);
|
||||
using AT = std::allocator_traits<Allocator>;
|
||||
auto ptr = AT::allocate(a, n); // may throw
|
||||
static_assert(std::is_trivially_copyable<decltype(ptr)>::value,
|
||||
"ptr must be trivially copyable");
|
||||
auto it = ptr;
|
||||
const auto end = ptr + n;
|
||||
try {
|
||||
// this loop may throw
|
||||
while (it != end) AT::construct(a, it++, *iter++);
|
||||
} catch (...) {
|
||||
// release resources that were already acquired before rethrowing
|
||||
while (it != ptr) AT::destroy(a, --it);
|
||||
AT::deallocate(a, ptr, n);
|
||||
throw;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
void destroy_buffer(Allocator& a, typename std::allocator_traits<Allocator>::pointer p,
|
||||
std::size_t n) {
|
||||
BOOST_ASSERT(p);
|
||||
BOOST_ASSERT(n > 0u);
|
||||
using AT = std::allocator_traits<Allocator>;
|
||||
auto it = p + n;
|
||||
while (it != p) AT::destroy(a, --it);
|
||||
AT::deallocate(a, p, n);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
Memory-efficient storage for integral counters which cannot overflow.
|
||||
|
||||
This storage provides a no-overflow-guarantee if it is filled with integral weights
|
||||
only. This storage implementation keeps a contiguous array of elemental counters, one
|
||||
for each cell. If an operation is requested, which would overflow a counter, the whole
|
||||
array is replaced with another of a wider integral type, then the operation is executed.
|
||||
The storage uses integers of 8, 16, 32, 64 bits, and then switches to a multiprecision
|
||||
integral type, similar to those in
|
||||
[Boost.Multiprecision](https://www.boost.org/doc/libs/develop/libs/multiprecision/doc/html/index.html).
|
||||
|
||||
A scaling operation or adding a floating point number turns the elements into doubles,
|
||||
which voids the no-overflow-guarantee.
|
||||
*/
|
||||
template <class Allocator>
|
||||
class unlimited_storage {
|
||||
static_assert(
|
||||
std::is_same<typename std::allocator_traits<Allocator>::pointer,
|
||||
typename std::allocator_traits<Allocator>::value_type*>::value,
|
||||
"unlimited_storage requires allocator with trivial pointer type");
|
||||
|
||||
public:
|
||||
using allocator_type = Allocator;
|
||||
using value_type = double;
|
||||
using mp_int = detail::mp_int<
|
||||
typename std::allocator_traits<allocator_type>::template rebind_alloc<uint64_t>>;
|
||||
|
||||
private:
|
||||
using types = mp11::mp_list<uint8_t, uint16_t, uint32_t, uint64_t, mp_int, double>;
|
||||
|
||||
template <class T>
|
||||
static constexpr char type_index() noexcept {
|
||||
return static_cast<char>(mp11::mp_find<types, T>::value);
|
||||
}
|
||||
|
||||
struct buffer_type {
|
||||
allocator_type alloc;
|
||||
std::size_t size = 0;
|
||||
char type = 0;
|
||||
void* ptr = nullptr;
|
||||
|
||||
template <class F, class... Ts>
|
||||
decltype(auto) apply(F&& f, Ts&&... ts) const {
|
||||
// this is intentionally not a switch, the if-chain is faster in benchmarks
|
||||
if (type == type_index<uint8_t>())
|
||||
return f(static_cast<uint8_t*>(ptr), std::forward<Ts>(ts)...);
|
||||
if (type == type_index<uint16_t>())
|
||||
return f(static_cast<uint16_t*>(ptr), std::forward<Ts>(ts)...);
|
||||
if (type == type_index<uint32_t>())
|
||||
return f(static_cast<uint32_t*>(ptr), std::forward<Ts>(ts)...);
|
||||
if (type == type_index<uint64_t>())
|
||||
return f(static_cast<uint64_t*>(ptr), std::forward<Ts>(ts)...);
|
||||
if (type == type_index<mp_int>())
|
||||
return f(static_cast<mp_int*>(ptr), std::forward<Ts>(ts)...);
|
||||
return f(static_cast<double*>(ptr), std::forward<Ts>(ts)...);
|
||||
}
|
||||
|
||||
buffer_type(allocator_type a = {}) : alloc(std::move(a)) {}
|
||||
|
||||
buffer_type(buffer_type&& o) noexcept
|
||||
: alloc(std::move(o.alloc)), size(o.size), type(o.type), ptr(o.ptr) {
|
||||
o.size = 0;
|
||||
o.type = 0;
|
||||
o.ptr = nullptr;
|
||||
}
|
||||
|
||||
buffer_type& operator=(buffer_type&& o) noexcept {
|
||||
if (this != &o) {
|
||||
using std::swap;
|
||||
swap(alloc, o.alloc);
|
||||
swap(size, o.size);
|
||||
swap(type, o.type);
|
||||
swap(ptr, o.ptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
buffer_type(const buffer_type& o) : alloc(o.alloc) {
|
||||
o.apply([this, &o](auto* otp) {
|
||||
using T = detail::remove_cvref_t<decltype(*otp)>;
|
||||
this->template make<T>(o.size, otp);
|
||||
});
|
||||
}
|
||||
|
||||
buffer_type& operator=(const buffer_type& o) {
|
||||
*this = buffer_type(o);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~buffer_type() noexcept { destroy(); }
|
||||
|
||||
void destroy() noexcept {
|
||||
BOOST_ASSERT((ptr == nullptr) == (size == 0));
|
||||
if (ptr == nullptr) return;
|
||||
apply([this](auto* tp) {
|
||||
using T = detail::remove_cvref_t<decltype(*tp)>;
|
||||
using alloc_type =
|
||||
typename std::allocator_traits<allocator_type>::template rebind_alloc<T>;
|
||||
alloc_type a(alloc); // rebind allocator
|
||||
detail::destroy_buffer(a, tp, size);
|
||||
});
|
||||
size = 0;
|
||||
type = 0;
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4244) // possible loss of data
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
void make(std::size_t n) {
|
||||
// note: order of commands is to not leave buffer in invalid state upon throw
|
||||
destroy();
|
||||
if (n > 0) {
|
||||
// rebind allocator
|
||||
using alloc_type =
|
||||
typename std::allocator_traits<allocator_type>::template rebind_alloc<T>;
|
||||
alloc_type a(alloc);
|
||||
ptr = detail::create_buffer(a, n); // may throw
|
||||
}
|
||||
size = n;
|
||||
type = type_index<T>();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
void make(std::size_t n, U iter) {
|
||||
// note: iter may be current ptr, so create new buffer before deleting old buffer
|
||||
T* new_ptr = nullptr;
|
||||
const auto new_type = type_index<T>();
|
||||
if (n > 0) {
|
||||
// rebind allocator
|
||||
using alloc_type =
|
||||
typename std::allocator_traits<allocator_type>::template rebind_alloc<T>;
|
||||
alloc_type a(alloc);
|
||||
new_ptr = detail::create_buffer(a, n, iter); // may throw
|
||||
}
|
||||
destroy();
|
||||
size = n;
|
||||
type = new_type;
|
||||
ptr = new_ptr;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class Buffer>
|
||||
class reference_t {
|
||||
public:
|
||||
reference_t(Buffer* b, std::size_t i) : buffer_(b), idx_(i) {}
|
||||
|
||||
reference_t(const reference_t&) = default;
|
||||
reference_t& operator=(const reference_t&) = delete; // references do not rebind
|
||||
reference_t& operator=(reference_t&&) = delete; // references do not rebind
|
||||
|
||||
// minimal operators for partial ordering
|
||||
bool operator<(reference_t rhs) const { return op<detail::less>(rhs); }
|
||||
bool operator>(reference_t rhs) const { return op<detail::greater>(rhs); }
|
||||
bool operator==(reference_t rhs) const { return op<detail::equal>(rhs); }
|
||||
|
||||
// adapted copy from boost/operators.hpp for partial ordering
|
||||
friend bool operator<=(reference_t x, reference_t y) { return !(y < x); }
|
||||
friend bool operator>=(reference_t x, reference_t y) { return !(y > x); }
|
||||
friend bool operator!=(reference_t y, reference_t x) { return !(x == y); }
|
||||
|
||||
template <class U>
|
||||
bool operator<(const U& rhs) const {
|
||||
return op<detail::less>(rhs);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
bool operator>(const U& rhs) const {
|
||||
return op<detail::greater>(rhs);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
bool operator==(const U& rhs) const {
|
||||
return op<detail::equal>(rhs);
|
||||
}
|
||||
|
||||
// adapted copy from boost/operators.hpp
|
||||
template <class U>
|
||||
friend bool operator<=(reference_t x, const U& y) {
|
||||
if (detail::is_unsigned_integral<U>::value) return !(x > y);
|
||||
return (x < y) || (x == y);
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator>=(reference_t x, const U& y) {
|
||||
if (detail::is_unsigned_integral<U>::value) return !(x < y);
|
||||
return (x > y) || (x == y);
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator>(const U& x, reference_t y) {
|
||||
return y < x;
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator<(const U& x, reference_t y) {
|
||||
return y > x;
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator<=(const U& x, reference_t y) {
|
||||
if (detail::is_unsigned_integral<U>::value) return !(y < x);
|
||||
return (y > x) || (y == x);
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator>=(const U& x, reference_t y) {
|
||||
if (detail::is_unsigned_integral<U>::value) return !(y > x);
|
||||
return (y < x) || (y == x);
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator==(const U& y, reference_t x) {
|
||||
return x == y;
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator!=(const U& y, reference_t x) {
|
||||
return !(x == y);
|
||||
}
|
||||
template <class U>
|
||||
friend bool operator!=(reference_t y, const U& x) {
|
||||
return !(y == x);
|
||||
}
|
||||
|
||||
operator double() const {
|
||||
return buffer_->apply(
|
||||
[this](const auto* tp) { return static_cast<double>(tp[idx_]); });
|
||||
}
|
||||
|
||||
protected:
|
||||
template <class Binary, class U>
|
||||
bool op(const reference_t<U>& rhs) const {
|
||||
const auto i = idx_;
|
||||
const auto j = rhs.idx_;
|
||||
return buffer_->apply([i, j, &rhs](const auto* ptr) {
|
||||
const auto& pi = ptr[i];
|
||||
return rhs.buffer_->apply([&pi, j](const auto* q) { return Binary()(pi, q[j]); });
|
||||
});
|
||||
}
|
||||
|
||||
template <class Binary, class U>
|
||||
bool op(const U& rhs) const {
|
||||
const auto i = idx_;
|
||||
return buffer_->apply([i, &rhs](const auto* tp) { return Binary()(tp[i], rhs); });
|
||||
}
|
||||
|
||||
template <class U>
|
||||
friend class reference_t;
|
||||
|
||||
Buffer* buffer_;
|
||||
std::size_t idx_;
|
||||
};
|
||||
|
||||
public:
|
||||
using const_reference = reference_t<const buffer_type>;
|
||||
|
||||
class reference : public reference_t<buffer_type> {
|
||||
using base_type = reference_t<buffer_type>;
|
||||
|
||||
public:
|
||||
using base_type::base_type;
|
||||
|
||||
reference operator=(reference t) {
|
||||
t.buffer_->apply([this, &t](const auto* otp) { *this = otp[t.idx_]; });
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator=(const_reference t) {
|
||||
t.buffer_->apply([this, &t](const auto* otp) { *this = otp[t.idx_]; });
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
reference operator=(const U& t) {
|
||||
base_type::buffer_->apply([this, &t](auto* tp) {
|
||||
tp[this->idx_] = 0;
|
||||
adder()(tp, *(this->buffer_), this->idx_, t);
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
reference operator+=(const U& t) {
|
||||
base_type::buffer_->apply(adder(), *base_type::buffer_, base_type::idx_, t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
reference operator*=(const U& t) {
|
||||
base_type::buffer_->apply(multiplier(), *base_type::buffer_, base_type::idx_, t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
reference operator-=(const U& t) {
|
||||
return operator+=(-t);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
reference operator/=(const U& t) {
|
||||
return operator*=(1.0 / static_cast<double>(t));
|
||||
}
|
||||
|
||||
reference operator++() {
|
||||
base_type::buffer_->apply(incrementor(), *base_type::buffer_, base_type::idx_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// minimal operators for partial ordering
|
||||
bool operator<(reference rhs) const { return base_type::operator<(rhs); }
|
||||
bool operator>(reference rhs) const { return base_type::operator>(rhs); }
|
||||
bool operator==(reference rhs) const { return base_type::operator==(rhs); }
|
||||
|
||||
// adapted copy from boost/operators.hpp for partial ordering
|
||||
friend bool operator<=(reference x, reference y) { return !(y < x); }
|
||||
friend bool operator>=(reference x, reference y) { return !(y > x); }
|
||||
friend bool operator!=(reference y, reference x) { return !(x == y); }
|
||||
};
|
||||
|
||||
private:
|
||||
template <class Value, class Reference, class Buffer>
|
||||
class iterator_t
|
||||
: public boost::iterator_adaptor<iterator_t<Value, Reference, Buffer>, std::size_t,
|
||||
Value, std::random_access_iterator_tag, Reference,
|
||||
std::ptrdiff_t> {
|
||||
|
||||
public:
|
||||
iterator_t() = default;
|
||||
template <class V, class R, class B>
|
||||
iterator_t(const iterator_t<V, R, B>& it)
|
||||
: iterator_t::iterator_adaptor_(it.base()), buffer_(it.buffer_) {}
|
||||
iterator_t(Buffer* b, std::size_t i) noexcept
|
||||
: iterator_t::iterator_adaptor_(i), buffer_(b) {}
|
||||
|
||||
protected:
|
||||
template <class V, class R, class B>
|
||||
bool equal(const iterator_t<V, R, B>& rhs) const noexcept {
|
||||
return buffer_ == rhs.buffer_ && this->base() == rhs.base();
|
||||
}
|
||||
Reference dereference() const { return {buffer_, this->base()}; }
|
||||
|
||||
friend class ::boost::iterator_core_access;
|
||||
template <class V, class R, class B>
|
||||
friend class iterator_t;
|
||||
|
||||
private:
|
||||
Buffer* buffer_ = nullptr;
|
||||
};
|
||||
|
||||
public:
|
||||
using const_iterator = iterator_t<const value_type, const_reference, const buffer_type>;
|
||||
using iterator = iterator_t<value_type, reference, buffer_type>;
|
||||
|
||||
explicit unlimited_storage(allocator_type a = {}) : buffer(std::move(a)) {}
|
||||
unlimited_storage(const unlimited_storage&) = default;
|
||||
unlimited_storage& operator=(const unlimited_storage&) = default;
|
||||
unlimited_storage(unlimited_storage&&) = default;
|
||||
unlimited_storage& operator=(unlimited_storage&&) = default;
|
||||
|
||||
template <class T>
|
||||
unlimited_storage(const storage_adaptor<T>& s) {
|
||||
using V = detail::remove_cvref_t<decltype(s[0])>;
|
||||
constexpr auto ti = type_index<V>();
|
||||
detail::static_if_c<(ti < mp11::mp_size<types>::value)>(
|
||||
[&](auto) { buffer.template make<V>(s.size(), s.begin()); },
|
||||
[&](auto) { buffer.template make<double>(s.size(), s.begin()); }, 0);
|
||||
}
|
||||
|
||||
template <class Iterable, class = detail::requires_iterable<Iterable>>
|
||||
unlimited_storage& operator=(const Iterable& s) {
|
||||
*this = unlimited_storage(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const { return buffer.alloc; }
|
||||
|
||||
void reset(std::size_t s) { buffer.template make<uint8_t>(s); }
|
||||
|
||||
std::size_t size() const noexcept { return buffer.size; }
|
||||
|
||||
reference operator[](std::size_t i) noexcept { return {&buffer, i}; }
|
||||
const_reference operator[](std::size_t i) const noexcept { return {&buffer, i}; }
|
||||
|
||||
bool operator==(const unlimited_storage& o) const noexcept {
|
||||
if (size() != o.size()) return false;
|
||||
return buffer.apply([&o](const auto* ptr) {
|
||||
return o.buffer.apply([ptr, &o](const auto* optr) {
|
||||
return std::equal(ptr, ptr + o.size(), optr, detail::equal{});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator==(const T& o) const {
|
||||
if (size() != o.size()) return false;
|
||||
return buffer.apply([&o](const auto* ptr) {
|
||||
return std::equal(ptr, ptr + o.size(), std::begin(o), detail::equal{});
|
||||
});
|
||||
}
|
||||
|
||||
unlimited_storage& operator*=(const double x) {
|
||||
buffer.apply(multiplier(), buffer, x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator begin() noexcept { return {&buffer, 0}; }
|
||||
iterator end() noexcept { return {&buffer, size()}; }
|
||||
const_iterator begin() const noexcept { return {&buffer, 0}; }
|
||||
const_iterator end() const noexcept { return {&buffer, size()}; }
|
||||
|
||||
/// @private used by unit tests, not part of generic storage interface
|
||||
template <class T>
|
||||
unlimited_storage(std::size_t s, const T* p, allocator_type a = {})
|
||||
: buffer(std::move(a)) {
|
||||
buffer.template make<T>(s, p);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
|
||||
private:
|
||||
struct incrementor {
|
||||
template <class T, class Buffer>
|
||||
void operator()(T* tp, Buffer& b, std::size_t i) {
|
||||
if (!detail::safe_increment(tp[i])) {
|
||||
using U = mp11::mp_at_c<types, (type_index<T>() + 1)>;
|
||||
b.template make<U>(b.size, tp);
|
||||
++static_cast<U*>(b.ptr)[i];
|
||||
}
|
||||
}
|
||||
|
||||
template <class Buffer>
|
||||
void operator()(mp_int* tp, Buffer&, std::size_t i) {
|
||||
++tp[i];
|
||||
}
|
||||
|
||||
template <class Buffer>
|
||||
void operator()(double* tp, Buffer&, std::size_t i) {
|
||||
++tp[i];
|
||||
}
|
||||
};
|
||||
|
||||
struct adder {
|
||||
template <class Buffer, class U>
|
||||
void operator()(double* tp, Buffer&, std::size_t i, const U& x) {
|
||||
tp[i] += static_cast<double>(x);
|
||||
}
|
||||
|
||||
template <class T, class Buffer, class U>
|
||||
void operator()(T* tp, Buffer& b, std::size_t i, const U& x) {
|
||||
U_is_integral(std::is_integral<U>{}, tp, b, i, x);
|
||||
}
|
||||
|
||||
template <class T, class Buffer, class U>
|
||||
void U_is_integral(std::false_type, T* tp, Buffer& b, std::size_t i, const U& x) {
|
||||
b.template make<double>(b.size, tp);
|
||||
operator()(static_cast<double*>(b.ptr), b, i, x);
|
||||
}
|
||||
|
||||
template <class T, class Buffer, class U>
|
||||
void U_is_integral(std::true_type, T* tp, Buffer& b, std::size_t i, const U& x) {
|
||||
U_is_unsigned_integral(std::is_unsigned<U>{}, tp, b, i, x);
|
||||
}
|
||||
|
||||
template <class T, class Buffer, class U>
|
||||
void U_is_unsigned_integral(std::false_type, T* tp, Buffer& b, std::size_t i,
|
||||
const U& x) {
|
||||
if (x >= 0)
|
||||
U_is_unsigned_integral(std::true_type{}, tp, b, i, detail::make_unsigned(x));
|
||||
else
|
||||
U_is_integral(std::false_type{}, tp, b, i, static_cast<double>(x));
|
||||
}
|
||||
|
||||
template <class Buffer, class U>
|
||||
void U_is_unsigned_integral(std::true_type, mp_int* tp, Buffer&, std::size_t i,
|
||||
const U& x) {
|
||||
tp[i] += x;
|
||||
}
|
||||
|
||||
template <class T, class Buffer, class U>
|
||||
void U_is_unsigned_integral(std::true_type, T* tp, Buffer& b, std::size_t i,
|
||||
const U& x) {
|
||||
if (detail::safe_radd(tp[i], x)) return;
|
||||
using V = mp11::mp_at_c<types, (type_index<T>() + 1)>;
|
||||
b.template make<V>(b.size, tp);
|
||||
U_is_unsigned_integral(std::true_type{}, static_cast<V*>(b.ptr), b, i, x);
|
||||
}
|
||||
};
|
||||
|
||||
struct multiplier {
|
||||
template <class T, class Buffer>
|
||||
void operator()(T* tp, Buffer& b, const double x) {
|
||||
// potential lossy conversion that cannot be avoided
|
||||
b.template make<double>(b.size, tp);
|
||||
operator()(static_cast<double*>(b.ptr), b, x);
|
||||
}
|
||||
|
||||
template <class Buffer>
|
||||
void operator()(double* tp, Buffer& b, const double x) {
|
||||
for (auto end = tp + b.size; tp != end; ++tp) *tp *= x;
|
||||
}
|
||||
|
||||
template <class T, class Buffer, class U>
|
||||
void operator()(T* tp, Buffer& b, std::size_t i, const U& x) {
|
||||
b.template make<double>(b.size, tp);
|
||||
operator()(static_cast<double*>(b.ptr), b, i, x);
|
||||
}
|
||||
|
||||
template <class Buffer, class U>
|
||||
void operator()(double* tp, Buffer&, std::size_t i, const U& x) {
|
||||
tp[i] *= static_cast<double>(x);
|
||||
}
|
||||
};
|
||||
|
||||
buffer_type buffer;
|
||||
};
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
74
macx64/include/boost/histogram/unsafe_access.hpp
Normal file
74
macx64/include/boost/histogram/unsafe_access.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2018 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_UNSAFE_ACCESS_HPP
|
||||
#define BOOST_HISTOGRAM_UNSAFE_ACCESS_HPP
|
||||
|
||||
#include <boost/histogram/detail/axes.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
/// Unsafe read/write access to classes that potentially break consistency
|
||||
struct unsafe_access {
|
||||
/**
|
||||
Get axes.
|
||||
@param hist histogram.
|
||||
*/
|
||||
template <class Histogram>
|
||||
static auto& axes(Histogram& hist) {
|
||||
return hist.axes_;
|
||||
}
|
||||
|
||||
/// @copydoc axes()
|
||||
template <class Histogram>
|
||||
static const auto& axes(const Histogram& hist) {
|
||||
return hist.axes_;
|
||||
}
|
||||
|
||||
/**
|
||||
Get mutable axis reference with compile-time number.
|
||||
@param hist histogram.
|
||||
@tparam I axis index (optional, default: 0).
|
||||
*/
|
||||
template <class Histogram, unsigned I = 0>
|
||||
static decltype(auto) axis(Histogram& hist, std::integral_constant<unsigned, I> = {}) {
|
||||
detail::axis_index_is_valid(hist.axes_, I);
|
||||
return detail::axis_get<I>(hist.axes_);
|
||||
}
|
||||
|
||||
/**
|
||||
Get mutable axis reference with run-time number.
|
||||
@param hist histogram.
|
||||
@param i axis index.
|
||||
*/
|
||||
template <class Histogram>
|
||||
static decltype(auto) axis(Histogram& hist, unsigned i) {
|
||||
detail::axis_index_is_valid(hist.axes_, i);
|
||||
return detail::axis_get(hist.axes_, i);
|
||||
}
|
||||
|
||||
/**
|
||||
Get storage.
|
||||
@param hist histogram.
|
||||
*/
|
||||
template <class Histogram>
|
||||
static auto& storage(Histogram& hist) {
|
||||
return hist.storage_;
|
||||
}
|
||||
|
||||
/// @copydoc storage()
|
||||
template <class Histogram>
|
||||
static const auto& storage(const Histogram& hist) {
|
||||
return hist.storage_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user