use index_type consistently everywhere

This commit is contained in:
Hans Dembinski 2019-12-29 00:02:16 +01:00 committed by GitHub
parent 27a49217ff
commit 03d92967f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 133 additions and 135 deletions

View File

@ -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;

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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;

View File

@ -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.

View File

@ -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};

View File

@ -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

View File

@ -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>;

View File

@ -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;
} }

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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());
} }

View File

@ -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;
}); });

View File

@ -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)();
} }

View File

@ -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(

View File

@ -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);
} }

View File

@ -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

View File

@ -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);

View File

@ -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)");

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 << " ";

View File

@ -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;

View File

@ -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...));
} }

View File

@ -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;
} }