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