This commit is contained in:
Hans Dembinski 2022-09-16 18:03:17 +02:00
parent 4699dbc0e8
commit 3e264ae282
5 changed files with 127 additions and 1 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ __pycache__
*.pyc
.DS_Store
.vs*
.cache
*.info
tools/lcov-*
tools/codecov

View File

@ -7,7 +7,7 @@ include(BoostFetch)
# setup for google benchmark
set(CMAKE_BUILD_TYPE Release) # ok, only set in local scope
option(BENCHMARK_ENABLE_TESTING "" OFF)
boost_fetch(google/benchmark)
boost_fetch(google/benchmark TAG main)
function(add_benchmark NAME)

View File

@ -93,6 +93,20 @@ std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>&
return detail::handle_nonzero_width(os, x);
}
template <class T>
std::ostream& operator<<(std::ostream& os, const multi_sum<T>& v) {
os << "multi_sum(";
bool first = true;
for (const T& x : v)
if (first) {
first = false;
os << x;
} else
os << ", " << x;
os << ")";
return os;
}
} // namespace accumulators
} // namespace histogram
} // namespace boost

View File

@ -106,6 +106,9 @@ class mean;
template <class ValueType = double>
class weighted_mean;
template <class ValueType = double>
class multi_sum;
} // namespace accumulators
struct unsafe_access;

View File

@ -0,0 +1,108 @@
#ifndef BOOST_HISTOGRAM_MULTI_SUM_STORAGE_HPP
#define BOOST_HISTOGRAM_MULTI_SUM_STORAGE_HPP
#include <algorithm>
#include <boost/core/span.hpp>
#include <boost/histogram.hpp>
#include <boost/histogram/detail/iterator_adaptor.hpp>
#include <iostream>
#include <memory>
namespace boost {
namespace histogram {
namespace accumulators {
template <class T>
struct multi_sum : public boost::span<T> {
using boost::span<T>::span;
void operator()(boost::span<T> values) {
if (values.size() != this->size()) throw std::runtime_error("size does not match");
auto it = this->begin();
for (const T& x : values) *it++ += x;
}
};
} // namespace accumulators
template <class ElementType = double>
class multi_sum_storage {
public:
template <class T>
using multi_sum = accumulators::multi_sum<T>;
using element_type = ElementType;
using value_type = multi_sum<element_type>;
using reference = value_type;
using const_reference = multi_sum<const element_type>;
template <class T>
struct iterator_base
: public detail::iterator_adaptor<iterator_base<T>, std::size_t, multi_sum<T>> {
using base_type =
detail::iterator_adaptor<iterator_base<T>, std::size_t, multi_sum<T>>;
iterator_base(T* ptr, std::size_t idx, std::size_t nelem)
: base_type{idx}, ptr_{ptr}, nelem_{nelem} {}
iterator_base(const iterator_base& other)
: base_type(other), ptr_{other.ptr_}, nelem_{other.nelem_} {}
iterator_base& operator=(const iterator_base& other) {
if (this != &other) {
base_type::operator=(other);
ptr_ = other.ptr_;
nelem_ = other.nelem_;
}
return *this;
}
decltype(auto) operator*() {
return multi_sum<T>{ptr_ + this->base() * nelem_, nelem_};
}
T* ptr_;
std::size_t nelem_;
};
using iterator = iterator_base<element_type>;
using const_iterator = iterator_base<const element_type>;
static constexpr bool has_threading_support() { return false; }
multi_sum_storage(const std::size_t nelem) : nelem_{nelem} {}
std::size_t size() const { return size_; }
void reset(std::size_t n) {
size_ = n;
buffer_.reset(new element_type[n * nelem_]);
}
iterator begin() { return {buffer_.get(), 0, nelem_}; }
iterator end() { return {buffer_.get(), size_, nelem_}; }
const_iterator begin() const { return {buffer_.get(), 0, nelem_}; }
const_iterator end() const { return {buffer_.get(), size_, nelem_}; }
reference operator[](std::size_t i) {
return reference{buffer_.get() + i * nelem_, nelem_};
}
const_reference operator[](std::size_t i) const {
return const_reference{buffer_.get() + i * nelem_, nelem_};
}
template <class T>
bool operator==(const multi_sum_storage<T>& other) const {
if (size() != other.size()) return false;
return std::equal(buffer_._get(), buffer_.get() + size_ * nelem_, other.ptr_.get());
}
public:
std::size_t size_ = 0;
std::size_t nelem_;
std::unique_ptr<element_type[]> buffer_;
};
} // namespace histogram
} // namespace boost
#endif