mirror of
https://github.com/boostorg/histogram.git
synced 2026-02-19 02:22:10 +00:00
make accessor writeable
This commit is contained in:
@@ -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};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user