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
und Mechanik 54 (1974) 39-51.
*/
template <typename RealType>
template <class RealType>
class sum {
public:
sum() = default;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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); });
}
template <typename T, typename U>
template <class T, class U>
void axes_assign(T& t, const U& u) {
t.assign(u.begin(), u.end());
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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