make accessor writeable

This commit is contained in:
Hans Dembinski
2019-01-06 16:10:10 +01:00
parent dc9437044b
commit 347ac33d2c
2 changed files with 41 additions and 39 deletions

View File

@@ -21,94 +21,91 @@ namespace boost {
namespace histogram {
/// Range over histogram bins with multi-dimensional index.
template <typename Histogram>
template <class Histogram>
class BOOST_HISTOGRAM_NODISCARD indexed_range {
using value_type = typename Histogram::value_type;
using value_iterator = typename Histogram::const_iterator;
using value_type = typename detail::unqual<Histogram>::value_type;
using value_iterator = detail::unqual<decltype(std::declval<Histogram&>().begin())>;
struct cache_item {
int idx, begin, end, extend;
};
using cache_type = detail::axes_buffer<typename Histogram::axes_type, cache_item>;
using cache_type =
detail::axes_buffer<typename detail::unqual<Histogram>::axes_type, cache_item>;
public:
class accessor {
public:
class const_iterator
: public boost::iterator_adaptor<const_iterator,
class index_iterator
: public boost::iterator_adaptor<index_iterator,
typename cache_type::const_iterator> {
public:
const_iterator(typename cache_type::const_iterator i)
: const_iterator::iterator_adaptor_(i) {}
decltype(auto) operator*() const noexcept {
return const_iterator::base_reference()->idx;
}
index_iterator(typename cache_type::const_iterator i)
: index_iterator::iterator_adaptor_(i) {}
decltype(auto) operator*() const noexcept { return index_iterator::base()->idx; }
};
int operator[](unsigned d) const { return parent_.cache_[d].idx; }
auto begin() const { return const_iterator(parent_.cache_.begin()); }
auto end() const { return const_iterator(parent_.cache_.end()); }
auto size() const { return parent_.cache_.size(); }
int operator[](unsigned d) const { return parent_->cache_[d].idx; }
auto begin() const { return index_iterator(parent_->cache_.begin()); }
auto end() const { return index_iterator(parent_->cache_.end()); }
auto size() const { return parent_->cache_.size(); }
template <unsigned N>
decltype(auto) bin(std::integral_constant<unsigned, N>) const {
return parent_.hist_.axis(std::integral_constant<unsigned, N>())[(*this)[N]];
return parent_->hist_.axis(std::integral_constant<unsigned, N>())[(*this)[N]];
}
decltype(auto) bin(unsigned d) const { return parent_.hist_.axis(d)[(*this)[d]]; }
decltype(auto) bin(unsigned d) const { return parent_->hist_.axis(d)[(*this)[d]]; }
double density() const {
double x = 1;
auto it = begin();
parent_.hist_.for_each_axis([&](const auto& a) {
parent_->hist_.for_each_axis([&](const auto& a) {
const auto w = axis::traits::width_as<double>(a, *it++);
x *= w ? w : 1;
});
return *iter_ / x;
}
accessor(const indexed_range& parent, value_iterator i) : parent_(parent), iter_(i) {}
accessor(indexed_range* parent, value_iterator i) : parent_(parent), iter_(i) {}
decltype(auto) operator*() const noexcept { return *iter_; }
auto operator-> () const noexcept { return iter_; }
private:
const indexed_range& parent_;
indexed_range* parent_;
value_iterator iter_;
};
class const_iterator
: public boost::iterator_adaptor<const_iterator, value_iterator, accessor,
class range_iterator
: public boost::iterator_adaptor<range_iterator, value_iterator, accessor,
boost::forward_traversal_tag, accessor> {
public:
const_iterator(const indexed_range& p, value_iterator i) noexcept
: const_iterator::iterator_adaptor_(i), parent_(p) {}
range_iterator(indexed_range* p, value_iterator i) noexcept
: range_iterator::iterator_adaptor_(i), parent_(p) {}
auto operator*() const noexcept {
return accessor(parent_, const_iterator::base_reference());
}
accessor operator*() const noexcept { return {parent_, range_iterator::base()}; }
private:
friend class boost::iterator_core_access;
void increment() noexcept {
std::size_t stride = 1;
auto c = parent_.cache_.begin();
auto c = parent_->cache_.begin();
++c->idx;
++const_iterator::base_reference();
while (c->idx == c->end && ((c + 1) != parent_.cache_.end())) {
++range_iterator::base_reference();
while (c->idx == c->end && ((c + 1) != parent_->cache_.end())) {
c->idx = c->begin;
const_iterator::base_reference() -= (c->end - c->idx) * stride;
range_iterator::base_reference() -= (c->end - c->idx) * stride;
stride *= c->extend;
++c;
++c->idx;
const_iterator::base_reference() += stride;
range_iterator::base_reference() += stride;
}
}
const indexed_range& parent_;
mutable indexed_range* parent_;
};
indexed_range(const Histogram& h, bool include_extra_bins)
indexed_range(Histogram& h, bool include_extra_bins)
: hist_(h)
, include_extra_bins_(include_extra_bins)
, begin_(hist_.begin())
@@ -137,19 +134,19 @@ public:
});
}
decltype(auto) begin() const { return const_iterator(*this, begin_); }
decltype(auto) end() const { return const_iterator(*this, end_); }
range_iterator begin() noexcept { return {this, begin_}; }
range_iterator end() noexcept { return {this, end_}; }
private:
const Histogram& hist_;
Histogram& hist_;
const bool include_extra_bins_;
value_iterator begin_, end_;
mutable cache_type cache_;
}; // namespace histogram
template <typename Histogram>
indexed_range<detail::unqual<Histogram>> indexed(Histogram&& h,
bool include_extra_bins = false) {
indexed_range<std::remove_reference_t<Histogram>> indexed(
Histogram&& h, bool include_extra_bins = false) {
return {std::forward<Histogram>(h), include_extra_bins};
}