mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-11 13:14:06 +00:00
accessor [] to index and indices
This commit is contained in:
parent
07b91f013f
commit
f8ebf85a05
@ -56,7 +56,7 @@ int main() {
|
||||
Passing `coverage::all` as the optional second argument iterates over all bins.
|
||||
|
||||
- Access the value with the dereference operator. The proxy acts like a pointer to it.
|
||||
- Access the current index with operator[] of the accessor, passing the dimension d.
|
||||
- Access the current index with `index(d)` of the accessor, passing the dimension d.
|
||||
- Access the corresponding bin interval view with `bin(d)`. Use a compile-time number
|
||||
like 1_c instead of a normal number like 1, if possible, to make this call more
|
||||
efficent. The return type depends on the axis type (see the axis reference for
|
||||
@ -68,8 +68,8 @@ int main() {
|
||||
|
||||
std::ostringstream os;
|
||||
for (auto x : indexed(h, coverage::all)) {
|
||||
os << boost::format("bin %2i [%4.1f, %4.1f): %i\n") % x[0] % x.bin(0_c).lower() %
|
||||
x.bin(0_c).upper() % *x;
|
||||
os << boost::format("bin %2i [%4.1f, %4.1f): %i\n") % x.index() % x.bin().lower() %
|
||||
x.bin().upper() % *x;
|
||||
}
|
||||
|
||||
std::cout << os.str() << std::flush;
|
||||
|
@ -47,9 +47,10 @@ int main() {
|
||||
const auto& cat_axis = bh::axis::get<cat>(h.axis(0)); // get reference to category axis
|
||||
std::ostringstream os;
|
||||
for (auto x : bh::indexed(h)) {
|
||||
os << boost::format("(%i, %i, %i) %4s [%3.1f, %3.1f) [%3.1f, %3.1f) %3.0f\n") % x[0] %
|
||||
x[1] % x[2] % cat_axis[x[0]] % x.bin(1).lower() % x.bin(1).upper() %
|
||||
x.bin(2).lower() % x.bin(2).upper() % *x;
|
||||
os << boost::format("(%i, %i, %i) %4s [%3.1f, %3.1f) [%3.1f, %3.1f) %3.0f\n") %
|
||||
x.index(0) % x.index(1) % x.index(2) % cat_axis[x.index(0)] %
|
||||
x.bin(1).lower() % x.bin(1).upper() % x.bin(2).lower() % x.bin(2).upper() %
|
||||
*x;
|
||||
}
|
||||
|
||||
std::cout << os.str() << std::flush;
|
||||
|
@ -35,8 +35,8 @@ int main() {
|
||||
*/
|
||||
std::ostringstream os;
|
||||
for (auto x : bh::indexed(p)) {
|
||||
os << boost::format("bin %i [%3.1f, %3.1f) count %i mean %g\n") % x[0] %
|
||||
x.bin(0).lower() % x.bin(0).upper() % x->count() % x->value();
|
||||
os << boost::format("bin %i [%3.1f, %3.1f) count %i mean %g\n") % x.index() %
|
||||
x.bin().lower() % x.bin().upper() % x->count() % x->value();
|
||||
}
|
||||
|
||||
std::cout << os.str() << std::flush;
|
||||
|
@ -42,11 +42,11 @@ int main() {
|
||||
std::ostringstream os;
|
||||
for (auto x : indexed(h)) {
|
||||
// x is a special accessor object
|
||||
const auto i = x[0]; // current index along first axis
|
||||
const auto j = x[1]; // current index along second axis
|
||||
const auto b0 = x.bin(0); // current bin interval along first axis
|
||||
const auto b1 = x.bin(1); // current bin interval along second axis
|
||||
const auto v = *x; // "dereference" to get the bin value
|
||||
const auto i = x.index(0); // current index along first axis
|
||||
const auto j = x.index(1); // current index along second axis
|
||||
const auto b0 = x.bin(0); // current bin interval along first axis
|
||||
const auto b1 = x.bin(1); // current bin interval along second axis
|
||||
const auto v = *x; // "dereference" to get the bin value
|
||||
os << boost::format("%i %i [%2i, %i) [%2i, %i): %i\n") % i % j % b0.lower() %
|
||||
b0.upper() % b1.lower() % b1.upper() % v;
|
||||
}
|
||||
@ -62,7 +62,7 @@ int main() {
|
||||
// second argument `coverage::all` to walk over all bins
|
||||
std::ostringstream os2;
|
||||
for (auto x : indexed(h, coverage::all)) {
|
||||
os2 << boost::format("%2i %2i: %i\n") % x[0] % x[1] % *x;
|
||||
os2 << boost::format("%2i %2i: %i\n") % x.index(0) % x.index(1) % *x;
|
||||
}
|
||||
|
||||
std::cout << os2.str() << std::flush;
|
||||
|
@ -33,7 +33,7 @@ int main() {
|
||||
|
||||
std::ostringstream os;
|
||||
for (auto&& b : bh::indexed(h)) {
|
||||
os << "bin " << b[0] << " [" << b.bin(0) << "] " << *b << "\n";
|
||||
os << "bin " << b.index() << " [" << b.bin() << "] " << *b << "\n";
|
||||
}
|
||||
|
||||
std::cout << os.str() << std::endl;
|
||||
|
@ -40,7 +40,8 @@ int main() {
|
||||
assert(sum(h) == 3 && sum(hr0) == 3 && sum(hr1) == 3);
|
||||
|
||||
std::ostringstream os1;
|
||||
for (auto x : bh::indexed(h)) os1 << "(" << x[0] << ", " << x[1] << "): " << *x << "\n";
|
||||
for (auto x : bh::indexed(h))
|
||||
os1 << "(" << x.index(0) << ", " << x.index(1) << "): " << *x << "\n";
|
||||
std::cout << os1.str() << std::flush;
|
||||
assert(os1.str() == "(0, 0): 1\n"
|
||||
"(1, 0): 1\n"
|
||||
@ -50,14 +51,14 @@ int main() {
|
||||
"(2, 1): 1\n");
|
||||
|
||||
std::ostringstream os2;
|
||||
for (auto x : bh::indexed(hr0)) os2 << "(" << x[0] << ", -): " << *x << "\n";
|
||||
for (auto x : bh::indexed(hr0)) os2 << "(" << x.index(0) << ", -): " << *x << "\n";
|
||||
std::cout << os2.str() << std::flush;
|
||||
assert(os2.str() == "(0, -): 1\n"
|
||||
"(1, -): 1\n"
|
||||
"(2, -): 1\n");
|
||||
|
||||
std::ostringstream os3;
|
||||
for (auto x : bh::indexed(hr1)) os3 << "(- ," << x[0] << "): " << *x << "\n";
|
||||
for (auto x : bh::indexed(hr1)) os3 << "(- ," << x.index(0) << "): " << *x << "\n";
|
||||
std::cout << os3.str() << std::flush;
|
||||
assert(os3.str() == "(- ,0): 2\n"
|
||||
"(- ,1): 1\n");
|
||||
|
@ -51,7 +51,7 @@ auto project(const histogram<A, S>& h, std::integral_constant<unsigned, N>, Ns..
|
||||
auto idx = detail::make_stack_buffer<int>(unsafe_access::axes(result));
|
||||
for (auto x : indexed(h, coverage::all)) {
|
||||
auto i = idx.begin();
|
||||
mp11::mp_for_each<LN>([&i, &x](auto J) { *i++ = x[J]; });
|
||||
mp11::mp_for_each<LN>([&i, &x](auto J) { *i++ = x.index(J); });
|
||||
result.at(idx) += *x;
|
||||
}
|
||||
return result;
|
||||
@ -83,7 +83,7 @@ auto project(const histogram<A, S>& h, const Iterable& c) {
|
||||
auto idx = detail::make_stack_buffer<int>(unsafe_access::axes(result));
|
||||
for (auto x : indexed(h, coverage::all)) {
|
||||
auto i = idx.begin();
|
||||
for (auto d : c) *i++ = x[d];
|
||||
for (auto d : c) *i++ = x.index(d);
|
||||
result.at(idx) += *x;
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ decltype(auto) reduce(const Histogram& h, const C& options) {
|
||||
for (auto x : indexed(h, coverage::all)) {
|
||||
auto i = idx.begin();
|
||||
auto o = opts.begin();
|
||||
for (auto j : x) {
|
||||
for (auto j : x.indices()) {
|
||||
*i = (j - o->begin);
|
||||
if (*i <= -1)
|
||||
*i = -1;
|
||||
|
@ -84,25 +84,19 @@ public:
|
||||
void reset() { storage_.reset(storage_.size()); }
|
||||
|
||||
/// Get N-th axis
|
||||
template <unsigned N>
|
||||
decltype(auto) axis(std::integral_constant<unsigned, N>) {
|
||||
template <unsigned N = 0>
|
||||
decltype(auto) axis(std::integral_constant<unsigned, N> = {}) {
|
||||
detail::axis_index_is_valid(axes_, N);
|
||||
return detail::axis_get<N>(axes_);
|
||||
}
|
||||
|
||||
/// Get N-th axis (const version)
|
||||
template <unsigned N>
|
||||
decltype(auto) axis(std::integral_constant<unsigned, N>) const {
|
||||
template <unsigned N = 0>
|
||||
decltype(auto) axis(std::integral_constant<unsigned, N> = {}) const {
|
||||
detail::axis_index_is_valid(axes_, N);
|
||||
return detail::axis_get<N>(axes_);
|
||||
}
|
||||
|
||||
/// Get first axis (convenience for 1-d histograms)
|
||||
decltype(auto) axis() { return axis(std::integral_constant<unsigned, 0>()); }
|
||||
|
||||
/// Get first axis (convenience for 1-d histograms, const version)
|
||||
decltype(auto) axis() const { return axis(std::integral_constant<unsigned, 0>()); }
|
||||
|
||||
/// Get N-th axis with runtime index
|
||||
decltype(auto) axis(unsigned i) {
|
||||
detail::axis_index_is_valid(axes_, i);
|
||||
|
@ -36,13 +36,27 @@ class BOOST_HISTOGRAM_NODISCARD indexed_range {
|
||||
public:
|
||||
class accessor {
|
||||
public:
|
||||
class index_iterator
|
||||
: public boost::iterator_adaptor<index_iterator,
|
||||
typename cache_type::const_iterator> {
|
||||
class indices_view {
|
||||
public:
|
||||
index_iterator(typename cache_type::const_iterator i)
|
||||
: index_iterator::iterator_adaptor_(i) {}
|
||||
decltype(auto) operator*() const noexcept { return index_iterator::base()->idx; }
|
||||
class index_iterator
|
||||
: public boost::iterator_adaptor<index_iterator,
|
||||
typename cache_type::const_iterator> {
|
||||
public:
|
||||
index_iterator(typename cache_type::const_iterator i)
|
||||
: index_iterator::iterator_adaptor_(i) {}
|
||||
decltype(auto) operator*() const noexcept { return index_iterator::base()->idx; }
|
||||
};
|
||||
|
||||
auto begin() const { return index_iterator(cache_.begin()); }
|
||||
auto end() const { return index_iterator(cache_.end()); }
|
||||
auto size() const { return cache_.size(); }
|
||||
int operator[](unsigned d) const { return cache_[d].idx; }
|
||||
int at(unsigned d) const { return cache_.at(d).idx; }
|
||||
|
||||
private:
|
||||
indices_view(const cache_type& c) : cache_(c) {}
|
||||
const cache_type& cache_;
|
||||
friend class accessor;
|
||||
};
|
||||
|
||||
// pointer interface for value
|
||||
@ -50,26 +64,22 @@ public:
|
||||
decltype(auto) get() const noexcept { return *iter_; }
|
||||
decltype(auto) operator-> () const noexcept { return iter_; }
|
||||
|
||||
// array interface for ND index
|
||||
int operator[](unsigned d) const { return parent_->cache_[d].idx; }
|
||||
int at(unsigned d) const { return parent_->cache_.at(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(); }
|
||||
|
||||
// convenience interface
|
||||
template <unsigned N>
|
||||
decltype(auto) bin(std::integral_constant<unsigned, N>) const {
|
||||
return parent_->hist_.axis(std::integral_constant<unsigned, N>())[(*this)[N]];
|
||||
int index(unsigned d = 0) const { return parent_->cache_[d].idx; }
|
||||
auto indices() const { return indices_view(parent_->cache_); }
|
||||
|
||||
template <unsigned N = 0>
|
||||
decltype(auto) bin(std::integral_constant<unsigned, N> = {}) const {
|
||||
return parent_->hist_.axis(std::integral_constant<unsigned, N>())[index(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)[index(d)]; }
|
||||
|
||||
double density() const {
|
||||
double x = 1;
|
||||
auto it = begin();
|
||||
auto it = parent_->cache_.begin();
|
||||
parent_->hist_.for_each_axis([&](const auto& a) {
|
||||
const auto w = axis::traits::width_as<double>(a, *it++);
|
||||
const auto w = axis::traits::width_as<double>(a, it++->idx);
|
||||
x *= w ? w : 1;
|
||||
});
|
||||
return *iter_ / x;
|
||||
@ -77,10 +87,8 @@ public:
|
||||
|
||||
private:
|
||||
accessor(indexed_range* parent, histogram_iterator i) : parent_(parent), iter_(i) {}
|
||||
|
||||
indexed_range* parent_;
|
||||
histogram_iterator iter_;
|
||||
|
||||
friend class indexed_range;
|
||||
};
|
||||
|
||||
|
@ -59,7 +59,7 @@ void run_tests() {
|
||||
BOOST_TEST_EQ(hr.axis(0)[3].upper(), 5);
|
||||
BOOST_TEST_EQ(hr.axis(1)[0].lower(), -1);
|
||||
BOOST_TEST_EQ(hr.axis(1)[2].upper(), 2);
|
||||
for (auto x : indexed(h, coverage::all)) BOOST_TEST_EQ(hr.at(x), *x);
|
||||
for (auto x : indexed(h, coverage::all)) BOOST_TEST_EQ(hr.at(x.indices()), *x);
|
||||
BOOST_TEST_EQ(hr, h);
|
||||
|
||||
hr = reduce(h, shrink(0, 2, 4));
|
||||
|
@ -59,8 +59,8 @@ int main() {
|
||||
BOOST_TEST_EQ(h.at(0, 0), 1);
|
||||
for (auto&& x : indexed(h)) {
|
||||
BOOST_TEST_THROWS(x.density(), std::runtime_error); // cannot use density method
|
||||
BOOST_TEST_EQ(x[0], 2.0 * x.bin(0_c).lower() / si::meter);
|
||||
BOOST_TEST_EQ(x[1], 2.0 * x.bin(1_c).lower());
|
||||
BOOST_TEST_EQ(x.index(0), 2.0 * x.bin(0_c).lower() / si::meter);
|
||||
BOOST_TEST_EQ(x.index(1), 2.0 * x.bin(1_c).lower());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,28 +32,28 @@ void run_1d_tests(mp_list<IsDynamic, Coverage>) {
|
||||
|
||||
auto ind = indexed(h, Coverage());
|
||||
auto it = ind.begin();
|
||||
BOOST_TEST_EQ(it->size(), 1);
|
||||
BOOST_TEST_EQ(it->indices().size(), 1);
|
||||
|
||||
if (Coverage() == coverage::all) {
|
||||
BOOST_TEST_EQ(it->operator[](0), -1);
|
||||
BOOST_TEST_EQ(it->index(0), -1);
|
||||
BOOST_TEST_EQ(**it, 1);
|
||||
BOOST_TEST_EQ(it->bin(0), h.axis()[-1]);
|
||||
++it;
|
||||
}
|
||||
BOOST_TEST_EQ(it->operator[](0), 0);
|
||||
BOOST_TEST_EQ(it->index(0), 0);
|
||||
BOOST_TEST_EQ(**it, 2);
|
||||
BOOST_TEST_EQ(it->bin(0), h.axis()[0]);
|
||||
++it;
|
||||
BOOST_TEST_EQ(it->operator[](0), 1);
|
||||
BOOST_TEST_EQ(it->index(0), 1);
|
||||
BOOST_TEST_EQ(**it, 3);
|
||||
BOOST_TEST_EQ(it->bin(0), h.axis()[1]);
|
||||
++it;
|
||||
BOOST_TEST_EQ(it->operator[](0), 2);
|
||||
BOOST_TEST_EQ(it->index(0), 2);
|
||||
BOOST_TEST_EQ(**it, 4);
|
||||
BOOST_TEST_EQ(it->bin(0), h.axis()[2]);
|
||||
++it;
|
||||
if (Coverage() == coverage::all) {
|
||||
BOOST_TEST_EQ(it->operator[](0), 3);
|
||||
BOOST_TEST_EQ(it->index(0), 3);
|
||||
BOOST_TEST_EQ(**it, 5);
|
||||
BOOST_TEST_EQ(it->bin(0), h.axis()[3]);
|
||||
++it;
|
||||
@ -78,7 +78,7 @@ void run_3d_tests(mp_list<IsDynamic, Coverage>) {
|
||||
|
||||
auto ind = indexed(h, Coverage());
|
||||
auto it = ind.begin();
|
||||
BOOST_TEST_EQ(it->size(), 3);
|
||||
BOOST_TEST_EQ(it->indices().size(), 3);
|
||||
|
||||
const int d = Coverage() == coverage::all;
|
||||
|
||||
@ -86,9 +86,9 @@ void run_3d_tests(mp_list<IsDynamic, Coverage>) {
|
||||
for (int k = 0; k < 4 + d; ++k)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
for (int i = -d; i < 2 + d; ++i) {
|
||||
BOOST_TEST_EQ(it->operator[](0), i);
|
||||
BOOST_TEST_EQ(it->operator[](1), j);
|
||||
BOOST_TEST_EQ(it->operator[](2), k);
|
||||
BOOST_TEST_EQ(it->index(0), i);
|
||||
BOOST_TEST_EQ(it->index(1), j);
|
||||
BOOST_TEST_EQ(it->index(2), k);
|
||||
BOOST_TEST_EQ(it->bin(0_c), h.axis(0_c)[i]);
|
||||
BOOST_TEST_EQ(it->bin(1_c), h.axis(1_c)[j]);
|
||||
BOOST_TEST_EQ(it->bin(2_c), h.axis(2_c)[k]);
|
||||
|
@ -62,9 +62,9 @@ static void IndexedLoop(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
for (auto x : boost::histogram::indexed(h, cov)) {
|
||||
benchmark::DoNotOptimize(*x);
|
||||
benchmark::DoNotOptimize(x[0]);
|
||||
benchmark::DoNotOptimize(x[1]);
|
||||
benchmark::DoNotOptimize(x[2]);
|
||||
benchmark::DoNotOptimize(x.index(0));
|
||||
benchmark::DoNotOptimize(x.index(1));
|
||||
benchmark::DoNotOptimize(x.index(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user