mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-09 23:04:07 +00:00
use index_type consistently everywhere
This commit is contained in:
parent
27a49217ff
commit
03d92967f9
@ -28,7 +28,7 @@ namespace accumulators {
|
||||
A. Neumaier, Zeitschrift fuer Angewandte Mathematik
|
||||
und Mechanik 54 (1974) 39-51.
|
||||
*/
|
||||
template <typename RealType>
|
||||
template <class RealType>
|
||||
class sum {
|
||||
public:
|
||||
sum() = default;
|
||||
|
@ -23,7 +23,7 @@ namespace accumulators {
|
||||
Uses West's incremental algorithm to improve numerical stability
|
||||
of mean and variance computation.
|
||||
*/
|
||||
template <typename RealType>
|
||||
template <class RealType>
|
||||
class weighted_mean {
|
||||
public:
|
||||
weighted_mean() = default;
|
||||
@ -45,7 +45,7 @@ public:
|
||||
sum_of_weighted_deltas_squared_ += w.value * delta * (x - weighted_mean_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <class T>
|
||||
weighted_mean& operator+=(const weighted_mean<T>& rhs) {
|
||||
if (sum_of_weights_ != 0 || rhs.sum_of_weights_ != 0) {
|
||||
const auto tmp = weighted_mean_ * sum_of_weights_ +
|
||||
@ -65,7 +65,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <class 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_ &&
|
||||
@ -73,7 +73,7 @@ public:
|
||||
sum_of_weighted_deltas_squared_ == rhs.sum_of_weighted_deltas_squared_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <class T>
|
||||
bool operator!=(const T& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
weighted_sum& operator++() { return operator+=(1); }
|
||||
|
||||
/// Increment by value.
|
||||
template <typename T>
|
||||
template <class T>
|
||||
weighted_sum& operator+=(const T& value) {
|
||||
sum_of_weights_ += value;
|
||||
sum_of_weights_squared_ += value * value;
|
||||
@ -40,7 +40,7 @@ public:
|
||||
}
|
||||
|
||||
/// Added another weighted sum.
|
||||
template <typename T>
|
||||
template <class 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_);
|
||||
@ -58,13 +58,13 @@ public:
|
||||
return sum_of_weights_ == rhs && sum_of_weights_squared_ == rhs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <class 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>
|
||||
template <class T>
|
||||
bool operator!=(const T& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
@ -27,10 +27,9 @@ namespace detail {
|
||||
struct reduce_option {
|
||||
unsigned iaxis = 0;
|
||||
bool indices_set = false;
|
||||
axis::index_type begin = 0, end = 0;
|
||||
axis::index_type begin = 0, end = 0, merge = 0;
|
||||
bool values_set = false;
|
||||
double lower = 0.0, upper = 0.0;
|
||||
unsigned merge = 0;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
@ -55,7 +54,7 @@ inline reduce_option shrink_and_rebin(unsigned iaxis, double lower, double upper
|
||||
if (lower == upper)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("lower != upper required"));
|
||||
if (merge == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("merge > 0 required"));
|
||||
return {iaxis, false, 0, 0, true, lower, upper, merge};
|
||||
return {iaxis, false, 0, 0, static_cast<axis::index_type>(merge), true, lower, upper};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,7 +73,7 @@ inline reduce_option slice_and_rebin(unsigned iaxis, axis::index_type begin,
|
||||
if (!(begin < end))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("begin < end required"));
|
||||
if (merge == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("merge > 0 required"));
|
||||
return {iaxis, true, begin, end, false, 0.0, 0.0, merge};
|
||||
return {iaxis, true, begin, end, static_cast<axis::index_type>(merge), false, 0.0, 0.0};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,7 +90,7 @@ inline reduce_option slice_and_rebin(unsigned iaxis, axis::index_type begin,
|
||||
the lower edge.
|
||||
*/
|
||||
inline reduce_option shrink(unsigned iaxis, double lower, double upper) {
|
||||
return shrink_and_rebin(iaxis, lower, upper, 1);
|
||||
return shrink_and_rebin(iaxis, lower, upper, 1u);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,7 +101,7 @@ inline reduce_option shrink(unsigned iaxis, double lower, double upper) {
|
||||
@param end one past the last index that should be kept.
|
||||
*/
|
||||
inline reduce_option slice(unsigned iaxis, axis::index_type begin, axis::index_type end) {
|
||||
return slice_and_rebin(iaxis, begin, end, 1);
|
||||
return slice_and_rebin(iaxis, begin, end, 1u);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,7 +112,8 @@ inline reduce_option slice(unsigned iaxis, axis::index_type begin, axis::index_t
|
||||
*/
|
||||
inline reduce_option rebin(unsigned iaxis, unsigned merge) {
|
||||
if (merge == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("merge > 0 required"));
|
||||
return reduce_option{iaxis, false, 0, 0, false, 0.0, 0.0, merge};
|
||||
return reduce_option{iaxis, false, 0, 0, static_cast<axis::index_type>(merge),
|
||||
false, 0.0, 0.0};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,7 +243,7 @@ decltype(auto) reduce(const Histogram& hist, const Iterable& options) {
|
||||
o.end = axis::traits::index(ain, o.upper);
|
||||
if (axis::traits::value_as<double>(ain, o.end) != o.upper) ++o.end;
|
||||
}
|
||||
o.begin = (std::max)(0, o.begin);
|
||||
if (o.begin < 0) o.begin = 0;
|
||||
o.end = (std::min)(o.end, ain.size());
|
||||
}
|
||||
o.end -= (o.end - o.begin) % o.merge;
|
||||
@ -288,7 +288,7 @@ decltype(auto) reduce(const Histogram& hist, const Iterable& options) {
|
||||
if (*i < ir->first) valid = false;
|
||||
} else {
|
||||
*i /= o->merge;
|
||||
const int end = (o->end - o->begin) / o->merge;
|
||||
const auto end = (o->end - o->begin) / o->merge;
|
||||
if (*i >= end) {
|
||||
*i = end;
|
||||
if (*i >= ir->second) valid = false;
|
||||
|
@ -108,11 +108,11 @@ public:
|
||||
}
|
||||
|
||||
/// Returns index and shift (if axis has grown) for the passed argument.
|
||||
auto update(const value_type& x) {
|
||||
std::pair<index_type, index_type> update(const value_type& x) {
|
||||
const auto i = index(x);
|
||||
if (i < size()) return std::make_pair(i, 0);
|
||||
if (i < size()) return {i, 0};
|
||||
vec_.emplace_back(x);
|
||||
return std::make_pair(i, -1);
|
||||
return {i, -1};
|
||||
}
|
||||
|
||||
/// Return value for index argument.
|
||||
|
@ -92,32 +92,50 @@ public:
|
||||
|
||||
/// Return index for value argument.
|
||||
index_type index(value_type x) const noexcept {
|
||||
return index_impl(std::is_floating_point<value_type>(), x);
|
||||
return detail::static_if<std::is_floating_point<value_type>>(
|
||||
[this](const auto z) -> index_type {
|
||||
// need to handle NaN, cannot simply cast to int and call int-implementation
|
||||
if (options_type::test(option::circular)) {
|
||||
if (std::isfinite(z))
|
||||
return static_cast<index_type>(std::floor(z) -
|
||||
std::floor(z / this->size()) * this->size());
|
||||
} else if (z < this->size())
|
||||
return z >= 0 ? static_cast<index_type>(z) : -1;
|
||||
return this->size();
|
||||
},
|
||||
[this](const auto z) -> index_type {
|
||||
if (options_type::test(option::circular))
|
||||
return static_cast<index_type>(z - std::floor(float(z) / this->size()) *
|
||||
this->size());
|
||||
if (z < this->size()) return z >= 0 ? z : -1;
|
||||
return this->size();
|
||||
},
|
||||
x - min_);
|
||||
}
|
||||
|
||||
/// Returns index and shift (if axis has grown) for the passed argument.
|
||||
auto update(value_type x) noexcept {
|
||||
auto impl = [this](long x) {
|
||||
auto impl = [this](long x) -> std::pair<index_type, index_type> {
|
||||
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);
|
||||
if (k < size()) return {k, 0};
|
||||
const auto n = k - size() + 1;
|
||||
size_ += n;
|
||||
return std::make_pair(k, -n);
|
||||
return {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_ -= k;
|
||||
return std::make_pair(0, -k);
|
||||
return {0, -k};
|
||||
};
|
||||
|
||||
return detail::static_if<std::is_floating_point<value_type>>(
|
||||
[this, impl](auto x) {
|
||||
[this, impl](auto x) -> std::pair<index_type, index_type> {
|
||||
if (std::isfinite(x)) return impl(static_cast<long>(std::floor(x)));
|
||||
return std::make_pair(x < 0 ? -1 : this->size(), 0);
|
||||
return {x < 0 ? -1 : this->size(), 0};
|
||||
},
|
||||
impl, x);
|
||||
}
|
||||
@ -170,27 +188,6 @@ public:
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
index_type size_{0};
|
||||
value_type min_{0};
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_INTERVAL_VIEW_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_INTERVAL_VIEW_HPP
|
||||
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
@ -16,12 +18,12 @@ namespace axis {
|
||||
|
||||
Represents the current bin interval.
|
||||
*/
|
||||
template <typename Axis>
|
||||
template <class Axis>
|
||||
class interval_view {
|
||||
public:
|
||||
interval_view(const Axis& axis, int idx) : axis_(axis), idx_(idx) {}
|
||||
interval_view(const Axis& axis, index_type idx) : axis_(axis), idx_(idx) {}
|
||||
// avoid viewing a temporary that goes out of scope
|
||||
interval_view(Axis&& axis, int idx) = delete;
|
||||
interval_view(Axis&& axis, index_type idx) = delete;
|
||||
|
||||
/// Return lower edge of bin.
|
||||
decltype(auto) lower() const noexcept { return axis_.value(idx_); }
|
||||
@ -32,19 +34,19 @@ public:
|
||||
/// Return width of bin.
|
||||
decltype(auto) width() const noexcept { return upper() - lower(); }
|
||||
|
||||
template <typename BinType>
|
||||
template <class BinType>
|
||||
bool operator==(const BinType& rhs) const noexcept {
|
||||
return lower() == rhs.lower() && upper() == rhs.upper();
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
template <class BinType>
|
||||
bool operator!=(const BinType& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
const Axis& axis_;
|
||||
const int idx_;
|
||||
const index_type idx_;
|
||||
};
|
||||
|
||||
} // namespace axis
|
||||
|
@ -16,11 +16,12 @@ namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
template <class Axis>
|
||||
class iterator : public detail::iterator_adaptor<iterator<Axis>, int,
|
||||
class iterator : public detail::iterator_adaptor<iterator<Axis>, index_type,
|
||||
decltype(std::declval<Axis>().bin(0))> {
|
||||
public:
|
||||
/// Make iterator from axis and index.
|
||||
iterator(const Axis& axis, int idx) : iterator::iterator_adaptor_(idx), axis_(axis) {}
|
||||
iterator(const Axis& axis, index_type idx)
|
||||
: iterator::iterator_adaptor_(idx), axis_(axis) {}
|
||||
|
||||
/// Return current bin object.
|
||||
decltype(auto) operator*() const { return axis_.bin(this->base()); }
|
||||
@ -30,7 +31,7 @@ private:
|
||||
};
|
||||
|
||||
/// Uses CRTP to inject iterator logic into Derived.
|
||||
template <typename Derived>
|
||||
template <class Derived>
|
||||
class iterator_mixin {
|
||||
public:
|
||||
using const_iterator = iterator<Derived>;
|
||||
|
@ -31,7 +31,7 @@ namespace axis {
|
||||
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.
|
||||
*/
|
||||
template <typename RealType>
|
||||
template <class RealType>
|
||||
class polymorphic_bin {
|
||||
using value_type = RealType;
|
||||
|
||||
@ -51,12 +51,12 @@ public:
|
||||
/// Return width of bin.
|
||||
value_type width() const noexcept { return upper() - lower(); }
|
||||
|
||||
template <typename BinType>
|
||||
template <class BinType>
|
||||
bool operator==(const BinType& rhs) const noexcept {
|
||||
return equal_impl(detail::has_method_lower<BinType>(), rhs);
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
template <class BinType>
|
||||
bool operator!=(const BinType& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
@ -69,12 +69,12 @@ private:
|
||||
return lower_or_value_ == rhs.lower_or_value_ && upper_ == rhs.upper_;
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
template <class BinType>
|
||||
bool equal_impl(std::true_type, const BinType& rhs) const noexcept {
|
||||
return lower() == rhs.lower() && upper() == rhs.upper();
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
template <class BinType>
|
||||
bool equal_impl(std::false_type, const BinType& rhs) const noexcept {
|
||||
return is_discrete() && static_cast<value_type>(*this) == rhs;
|
||||
}
|
||||
|
@ -307,13 +307,13 @@ public:
|
||||
}
|
||||
|
||||
/// Returns index and shift (if axis has grown) for the passed argument.
|
||||
auto update(value_type x) noexcept {
|
||||
std::pair<index_type, index_type> 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);
|
||||
return {i, 0};
|
||||
}
|
||||
if (z != -std::numeric_limits<internal_value_type>::infinity()) {
|
||||
const auto stop = min_ + delta_;
|
||||
@ -321,10 +321,10 @@ public:
|
||||
min_ += i * (delta_ / size());
|
||||
delta_ = stop - min_;
|
||||
size_ -= i;
|
||||
return std::make_pair(0, -i);
|
||||
return {0, -i};
|
||||
}
|
||||
// z is -infinity
|
||||
return std::make_pair(-1, 0);
|
||||
return {-1, 0};
|
||||
}
|
||||
// z either beyond range, infinite, or NaN
|
||||
if (z < std::numeric_limits<internal_value_type>::infinity()) {
|
||||
@ -333,10 +333,10 @@ public:
|
||||
delta_ /= size();
|
||||
delta_ *= size() + n;
|
||||
size_ += n;
|
||||
return std::make_pair(i, -n);
|
||||
return {i, -n};
|
||||
}
|
||||
// z either infinite or NaN
|
||||
return std::make_pair(size(), 0);
|
||||
return {size(), 0};
|
||||
}
|
||||
|
||||
/// Return value for fractional index argument.
|
||||
|
@ -354,7 +354,10 @@ std::pair<index_type, index_type> update(Axis& axis, const U& value) noexcept(
|
||||
[&value](auto& a) {
|
||||
return a.update(detail::try_cast<value_type<Axis>, std::invalid_argument>(value));
|
||||
},
|
||||
[&value](auto& a) { return std::make_pair(index(a, value), index_type{0}); }, axis);
|
||||
[&value](auto& a) -> std::pair<index_type, index_type> {
|
||||
return {index(a, value), 0};
|
||||
},
|
||||
axis);
|
||||
}
|
||||
|
||||
// specialization for variant
|
||||
|
@ -137,7 +137,7 @@ public:
|
||||
vec_.begin() - 1);
|
||||
}
|
||||
|
||||
auto update(value_type x) noexcept {
|
||||
std::pair<index_type, index_type> update(value_type x) noexcept {
|
||||
const auto i = index(x);
|
||||
if (std::isfinite(x)) {
|
||||
if (0 <= i) {
|
||||
@ -146,14 +146,14 @@ public:
|
||||
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);
|
||||
return {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 {0, -i};
|
||||
}
|
||||
return std::make_pair(x < 0 ? -1 : size(), 0);
|
||||
return {x < 0 ? -1 : size(), 0};
|
||||
}
|
||||
|
||||
/// Return value for fractional index argument.
|
||||
|
@ -35,7 +35,7 @@ class variant : public iterator_mixin<variant<Ts...>> {
|
||||
template <class T>
|
||||
using is_bounded_type = mp11::mp_contains<variant, std::decay_t<T>>;
|
||||
|
||||
template <typename T>
|
||||
template <class 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
|
||||
@ -84,17 +84,17 @@ public:
|
||||
|
||||
/// Return size of axis.
|
||||
index_type size() const {
|
||||
return visit([](const auto& a) { return a.size(); }, *this);
|
||||
return visit([](const auto& a) -> index_type { return a.size(); }, *this);
|
||||
}
|
||||
|
||||
/// Return options of axis or option::none_t if axis has no options.
|
||||
unsigned options() const {
|
||||
return visit([](const auto& a) { return axis::traits::options(a); }, *this);
|
||||
return visit([](const auto& a) { return traits::options(a); }, *this);
|
||||
}
|
||||
|
||||
/// Returns true if the axis is inclusive or false.
|
||||
bool inclusive() const {
|
||||
return visit([](const auto& a) { return axis::traits::inclusive(a); }, *this);
|
||||
return visit([](const auto& a) { return traits::inclusive(a); }, *this);
|
||||
}
|
||||
|
||||
/// Return reference to const metadata or instance of null_type if axis has no
|
||||
|
@ -175,7 +175,7 @@ void axes_assign(T& t, const std::tuple<Us...>& u) {
|
||||
mp_for_each<mp_iota_c<sizeof...(Us)>>([&](auto I) { t[I] = std::get<I>(u); });
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
template <class T, class U>
|
||||
void axes_assign(T& t, const U& u) {
|
||||
t.assign(u.begin(), u.end());
|
||||
}
|
||||
|
@ -114,8 +114,8 @@ struct storage_grower {
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
// move storage pointer to index position; apply positive shifts if any
|
||||
ns += (dit->idx + (*sit >= 0 ? *sit : 0)) * dit->new_stride;
|
||||
++dit;
|
||||
++sit;
|
||||
});
|
||||
|
@ -13,7 +13,7 @@ namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
template <class T>
|
||||
constexpr T lowest() {
|
||||
return std::numeric_limits<T>::lowest();
|
||||
}
|
||||
@ -28,7 +28,7 @@ constexpr float lowest() {
|
||||
return -std::numeric_limits<float>::infinity();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <class T>
|
||||
constexpr T highest() {
|
||||
return (std::numeric_limits<T>::max)();
|
||||
}
|
||||
|
@ -371,7 +371,7 @@ public:
|
||||
}
|
||||
|
||||
/// Access cell value at integral indices stored in `std::tuple` (read-only).
|
||||
template <typename... Indices>
|
||||
template <class... Indices>
|
||||
decltype(auto) at(const std::tuple<Indices...>& is) const {
|
||||
if (rank() != sizeof...(Indices))
|
||||
BOOST_THROW_EXCEPTION(
|
||||
|
@ -28,7 +28,7 @@ namespace histogram {
|
||||
@param axis First axis instance.
|
||||
@param axes Other axis instances.
|
||||
*/
|
||||
template <typename Axis, typename... Axes, typename = detail::requires_axis<Axis>>
|
||||
template <class Axis, class... Axes, class = 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)...);
|
||||
@ -39,7 +39,7 @@ auto make_profile(Axis&& axis, Axes&&... axes) {
|
||||
@param axis First axis instance.
|
||||
@param axes Other axis instances.
|
||||
*/
|
||||
template <typename Axis, typename... Axes, typename = detail::requires_axis<Axis>>
|
||||
template <class Axis, class... Axes, class = 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)...);
|
||||
@ -49,7 +49,7 @@ auto make_weighted_profile(Axis&& axis, 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>>
|
||||
template <class Iterable, class = detail::requires_sequence_of_any_axis<Iterable>>
|
||||
auto make_profile(Iterable&& iterable) {
|
||||
return make_histogram_with(profile_storage(), std::forward<Iterable>(iterable));
|
||||
}
|
||||
@ -58,7 +58,7 @@ auto make_profile(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>>
|
||||
template <class Iterable, class = detail::requires_sequence_of_any_axis<Iterable>>
|
||||
auto make_weighted_profile(Iterable&& iterable) {
|
||||
return make_histogram_with(weighted_profile_storage(),
|
||||
std::forward<Iterable>(iterable));
|
||||
@ -69,7 +69,7 @@ auto make_weighted_profile(Iterable&& iterable) {
|
||||
@param begin Iterator to range of axis objects.
|
||||
@param end Iterator to range of axis objects.
|
||||
*/
|
||||
template <typename Iterator, typename = detail::requires_iterator<Iterator>>
|
||||
template <class Iterator, class = detail::requires_iterator<Iterator>>
|
||||
auto make_profile(Iterator begin, Iterator end) {
|
||||
return make_histogram_with(profile_storage(), begin, end);
|
||||
}
|
||||
@ -79,7 +79,7 @@ auto make_profile(Iterator begin, Iterator end) {
|
||||
@param begin Iterator to range of axis objects.
|
||||
@param end Iterator to range of axis objects.
|
||||
*/
|
||||
template <typename Iterator, typename = detail::requires_iterator<Iterator>>
|
||||
template <class Iterator, class = detail::requires_iterator<Iterator>>
|
||||
auto make_weighted_profile(Iterator begin, Iterator end) {
|
||||
return make_histogram_with(weighted_profile_storage(), begin, end);
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ void ostream(OStream& os, const Histogram& h, const bool show_values = true) {
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
template <typename CharT, typename Traits, typename A, typename S>
|
||||
template <class CharT, class Traits, class A, class S>
|
||||
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
|
||||
const histogram<A, S>& h) {
|
||||
// save fmt
|
||||
|
@ -239,7 +239,7 @@ struct map_impl : T {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
template <class CharT, class Traits>
|
||||
friend std::basic_ostream<CharT, Traits>& operator<<(
|
||||
std::basic_ostream<CharT, Traits>& os, reference x) {
|
||||
os << static_cast<const_reference>(x);
|
||||
|
@ -133,15 +133,16 @@ int main() {
|
||||
|
||||
// axis::category with growth
|
||||
{
|
||||
using pii_t = std::pair<axis::index_type, axis::index_type>;
|
||||
axis::category<int, axis::null_type, axis::option::growth_t> a;
|
||||
BOOST_TEST_EQ(a.size(), 0);
|
||||
BOOST_TEST_EQ(a.update(5), std::make_pair(0, -1));
|
||||
BOOST_TEST_EQ(a.update(5), pii_t(0, -1));
|
||||
BOOST_TEST_EQ(a.size(), 1);
|
||||
BOOST_TEST_EQ(a.update(1), std::make_pair(1, -1));
|
||||
BOOST_TEST_EQ(a.update(1), pii_t(1, -1));
|
||||
BOOST_TEST_EQ(a.size(), 2);
|
||||
BOOST_TEST_EQ(a.update(10), std::make_pair(2, -1));
|
||||
BOOST_TEST_EQ(a.update(10), pii_t(2, -1));
|
||||
BOOST_TEST_EQ(a.size(), 3);
|
||||
BOOST_TEST_EQ(a.update(10), std::make_pair(2, 0));
|
||||
BOOST_TEST_EQ(a.update(10), pii_t(2, 0));
|
||||
BOOST_TEST_EQ(a.size(), 3);
|
||||
|
||||
BOOST_TEST_EQ(str(a), "category(5, 1, 10, options=growth)");
|
||||
|
@ -136,20 +136,18 @@ int main() {
|
||||
|
||||
// axis::integer with growth
|
||||
{
|
||||
using pii_t = std::pair<axis::index_type, axis::index_type>;
|
||||
axis::integer<double, axis::null_type, axis::option::growth_t> a;
|
||||
BOOST_TEST_EQ(a.size(), 0);
|
||||
BOOST_TEST_EQ(a.update(0), std::make_pair(0, -1));
|
||||
BOOST_TEST_EQ(a.update(0), pii_t(0, -1));
|
||||
BOOST_TEST_EQ(a.size(), 1);
|
||||
BOOST_TEST_EQ(a.update(1), std::make_pair(1, -1));
|
||||
BOOST_TEST_EQ(a.update(1), pii_t(1, -1));
|
||||
BOOST_TEST_EQ(a.size(), 2);
|
||||
BOOST_TEST_EQ(a.update(-1), std::make_pair(0, 1));
|
||||
BOOST_TEST_EQ(a.update(-1), pii_t(0, 1));
|
||||
BOOST_TEST_EQ(a.size(), 3);
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::infinity()),
|
||||
std::make_pair(a.size(), 0));
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::quiet_NaN()),
|
||||
std::make_pair(a.size(), 0));
|
||||
BOOST_TEST_EQ(a.update(-std::numeric_limits<double>::infinity()),
|
||||
std::make_pair(-1, 0));
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::infinity()), pii_t(a.size(), 0));
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::quiet_NaN()), pii_t(a.size(), 0));
|
||||
BOOST_TEST_EQ(a.update(-std::numeric_limits<double>::infinity()), pii_t(-1, 0));
|
||||
}
|
||||
|
||||
// iterators
|
||||
|
@ -197,28 +197,26 @@ int main() {
|
||||
|
||||
// with growth
|
||||
{
|
||||
using pii_t = std::pair<axis::index_type, axis::index_type>;
|
||||
axis::regular<double, def, def, axis::option::growth_t> a{1, 0, 1};
|
||||
BOOST_TEST_EQ(a.size(), 1);
|
||||
BOOST_TEST_EQ(a.update(0), std::make_pair(0, 0));
|
||||
BOOST_TEST_EQ(a.update(0), pii_t(0, 0));
|
||||
BOOST_TEST_EQ(a.size(), 1);
|
||||
BOOST_TEST_EQ(a.update(1), std::make_pair(1, -1));
|
||||
BOOST_TEST_EQ(a.update(1), pii_t(1, -1));
|
||||
BOOST_TEST_EQ(a.size(), 2);
|
||||
BOOST_TEST_EQ(a.value(0), 0);
|
||||
BOOST_TEST_EQ(a.value(2), 2);
|
||||
BOOST_TEST_EQ(a.update(-1), std::make_pair(0, 1));
|
||||
BOOST_TEST_EQ(a.update(-1), pii_t(0, 1));
|
||||
BOOST_TEST_EQ(a.size(), 3);
|
||||
BOOST_TEST_EQ(a.value(0), -1);
|
||||
BOOST_TEST_EQ(a.value(3), 2);
|
||||
BOOST_TEST_EQ(a.update(-10), std::make_pair(0, 9));
|
||||
BOOST_TEST_EQ(a.update(-10), pii_t(0, 9));
|
||||
BOOST_TEST_EQ(a.size(), 12);
|
||||
BOOST_TEST_EQ(a.value(0), -10);
|
||||
BOOST_TEST_EQ(a.value(12), 2);
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::infinity()),
|
||||
std::make_pair(a.size(), 0));
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::quiet_NaN()),
|
||||
std::make_pair(a.size(), 0));
|
||||
BOOST_TEST_EQ(a.update(-std::numeric_limits<double>::infinity()),
|
||||
std::make_pair(-1, 0));
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::infinity()), pii_t(a.size(), 0));
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::quiet_NaN()), pii_t(a.size(), 0));
|
||||
BOOST_TEST_EQ(a.update(-std::numeric_limits<double>::infinity()), pii_t(-1, 0));
|
||||
}
|
||||
|
||||
// iterators
|
||||
|
@ -94,31 +94,29 @@ int main() {
|
||||
|
||||
// axis::regular with growth
|
||||
{
|
||||
using pii_t = std::pair<axis::index_type, axis::index_type>;
|
||||
axis::variable<double, axis::null_type, axis::option::growth_t> a{0, 1};
|
||||
BOOST_TEST_EQ(a.size(), 1);
|
||||
BOOST_TEST_EQ(a.update(0), std::make_pair(0, 0));
|
||||
BOOST_TEST_EQ(a.update(0), pii_t(0, 0));
|
||||
BOOST_TEST_EQ(a.size(), 1);
|
||||
BOOST_TEST_EQ(a.update(1.1), std::make_pair(1, -1));
|
||||
BOOST_TEST_EQ(a.update(1.1), pii_t(1, -1));
|
||||
BOOST_TEST_EQ(a.size(), 2);
|
||||
BOOST_TEST_EQ(a.value(0), 0);
|
||||
BOOST_TEST_EQ(a.value(1), 1);
|
||||
BOOST_TEST_EQ(a.value(2), 1.5);
|
||||
BOOST_TEST_EQ(a.update(-0.1), std::make_pair(0, 1));
|
||||
BOOST_TEST_EQ(a.update(-0.1), pii_t(0, 1));
|
||||
BOOST_TEST_EQ(a.value(0), -0.5);
|
||||
BOOST_TEST_EQ(a.size(), 3);
|
||||
BOOST_TEST_EQ(a.update(10), std::make_pair(3, -1));
|
||||
BOOST_TEST_EQ(a.update(10), pii_t(3, -1));
|
||||
BOOST_TEST_EQ(a.size(), 4);
|
||||
BOOST_TEST_IS_CLOSE(a.value(4), 10, 1e-9);
|
||||
BOOST_TEST_EQ(a.update(-10), std::make_pair(0, 1));
|
||||
BOOST_TEST_EQ(a.update(-10), pii_t(0, 1));
|
||||
BOOST_TEST_EQ(a.size(), 5);
|
||||
BOOST_TEST_IS_CLOSE(a.value(0), -10, 1e-9);
|
||||
|
||||
BOOST_TEST_EQ(a.update(-std::numeric_limits<double>::infinity()),
|
||||
std::make_pair(-1, 0));
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::infinity()),
|
||||
std::make_pair(a.size(), 0));
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::quiet_NaN()),
|
||||
std::make_pair(a.size(), 0));
|
||||
BOOST_TEST_EQ(a.update(-std::numeric_limits<double>::infinity()), pii_t(-1, 0));
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::infinity()), pii_t(a.size(), 0));
|
||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::quiet_NaN()), pii_t(a.size(), 0));
|
||||
}
|
||||
|
||||
// iterators
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
namespace std {
|
||||
// never add to std, we only do it here to get ADL working :(
|
||||
template <typename T>
|
||||
template <class T>
|
||||
ostream& operator<<(ostream& os, const vector<T>& v) {
|
||||
os << "[ ";
|
||||
for (const auto& x : v) os << x << " ";
|
||||
|
@ -13,8 +13,8 @@
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
template <typename Axis>
|
||||
void test_axis_iterator(const Axis& a, int begin, int end) {
|
||||
template <class Axis>
|
||||
void test_axis_iterator(const Axis& a, axis::index_type begin, axis::index_type end) {
|
||||
for (auto bin : a) {
|
||||
BOOST_TEST_EQ(bin, a.bin(begin));
|
||||
++begin;
|
||||
|
@ -20,7 +20,7 @@
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
template <typename... Ts>
|
||||
template <class... Ts>
|
||||
auto make_axis_vector(const Ts&... ts) {
|
||||
// make sure the variant is never trivial (contains only one type)
|
||||
using R = axis::regular<double, boost::use_default, axis::null_type>;
|
||||
@ -34,22 +34,22 @@ auto make_axis_vector(const Ts&... ts) {
|
||||
using static_tag = std::false_type;
|
||||
using dynamic_tag = std::true_type;
|
||||
|
||||
template <typename... Axes>
|
||||
template <class... Axes>
|
||||
auto make(static_tag, const Axes&... axes) {
|
||||
return make_histogram(axes...);
|
||||
}
|
||||
|
||||
template <typename S, typename... Axes>
|
||||
template <class S, class... Axes>
|
||||
auto make_s(static_tag, S&& s, const Axes&... axes) {
|
||||
return make_histogram_with(s, axes...);
|
||||
}
|
||||
|
||||
template <typename... Axes>
|
||||
template <class... Axes>
|
||||
auto make(dynamic_tag, const Axes&... axes) {
|
||||
return make_histogram(make_axis_vector(axes...));
|
||||
}
|
||||
|
||||
template <typename S, typename... Axes>
|
||||
template <class S, class... Axes>
|
||||
auto make_s(dynamic_tag, S&& s, const Axes&... axes) {
|
||||
return make_histogram_with(s, make_axis_vector(axes...));
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ struct icast_identity {
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
template <class T>
|
||||
inline T implicit_cast(typename detail::icast_identity<T>::type x) {
|
||||
return x;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user