mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-09 23:04:07 +00:00
wip
This commit is contained in:
parent
98f634e232
commit
78dbdd52e5
@ -31,7 +31,7 @@
|
||||
#include <boost/histogram/literals.hpp>
|
||||
#include <boost/histogram/make_histogram.hpp>
|
||||
#include <boost/histogram/make_profile.hpp>
|
||||
#include <boost/histogram/multi_sum_storage.hpp>
|
||||
#include <boost/histogram/multi_storage.hpp>
|
||||
#include <boost/histogram/storage_adaptor.hpp>
|
||||
#include <boost/histogram/unlimited_storage.hpp>
|
||||
|
||||
|
112
include/boost/histogram/multi_storage.hpp
Normal file
112
include/boost/histogram/multi_storage.hpp
Normal file
@ -0,0 +1,112 @@
|
||||
// Copyright 2022 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_MULTI_STORAGE_HPP
|
||||
#define BOOST_HISTOGRAM_MULTI_STORAGE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/core/span.hpp>
|
||||
#include <boost/histogram/detail/iterator_adaptor.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
template <class ElementType = double>
|
||||
class multi_storage {
|
||||
public:
|
||||
using element_type = ElementType;
|
||||
|
||||
struct accumulator : public span<element_type> {
|
||||
using span<element_type>::span;
|
||||
|
||||
void operator()(span<const element_type> values) {
|
||||
if (values.size() != this->size()) throw std::runtime_error("size does not match");
|
||||
|
||||
auto it = this->begin();
|
||||
for (const element_type& v : values) {
|
||||
// TODO make this more flexible, support operator++ and operator()
|
||||
*it++ += v;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using value_type = std::vector<element_type>;
|
||||
using reference = span<element_type>;
|
||||
using const_reference = span<const element_type>;
|
||||
|
||||
template <class T>
|
||||
struct iterator_base
|
||||
: public detail::iterator_adaptor<iterator_base<T>, T*, span<T>, value_type> {
|
||||
using reference = typename iterator_base::reference;
|
||||
using difference_type = typename iterator_base::difference_type;
|
||||
|
||||
iterator_base(T* ptr, std::size_t nelem)
|
||||
: iterator_base::iterator_adaptor_{ptr}, nelem_{nelem} {}
|
||||
iterator_base(const iterator_base& other)
|
||||
: iterator_base::iterator_adaptor_(other), nelem_{other.nelem_} {}
|
||||
iterator_base& operator=(const iterator_base& other) {
|
||||
if (this != &other) {
|
||||
iterator_base::iterator_adaptor_::operator=(other);
|
||||
nelem_ = other.nelem_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_base& operator+=(difference_type n) {
|
||||
iterator_base::iterator_adaptor_::operator+=(n* nelem_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator*() { return {this->base(), nelem_}; }
|
||||
|
||||
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_storage(const std::size_t nelem) : nelem_{nelem} {}
|
||||
|
||||
std::size_t size() const { return size_; }
|
||||
std::size_t width() const { return nelem_; }
|
||||
|
||||
void reset(std::size_t n) {
|
||||
size_ = n;
|
||||
buffer_.reset(new element_type[n * nelem_]);
|
||||
}
|
||||
|
||||
iterator begin() { return {buffer_.get(), nelem_}; }
|
||||
iterator end() { return {buffer_.get() + size_ * nelem_, nelem_}; }
|
||||
|
||||
const_iterator begin() const { return {buffer_.get(), nelem_}; }
|
||||
const_iterator end() const { return {buffer_.get() + size_ * nelem_, nelem_}; }
|
||||
|
||||
reference operator[](std::size_t i) { return {buffer_.get() + i * nelem_, nelem_}; }
|
||||
const_reference operator[](std::size_t i) const {
|
||||
return {buffer_.get() + i * nelem_, nelem_};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator==(const multi_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
|
@ -1,108 +0,0 @@
|
||||
#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
|
@ -88,6 +88,7 @@ set_tests_properties(run-boost_histogram-histogram_ostream_ascii_test
|
||||
PROPERTIES ENVIRONMENT "LANG=FOO;COLUMNS=20")
|
||||
boost_test(TYPE run SOURCES histogram_test.cpp)
|
||||
boost_test(TYPE run SOURCES indexed_test.cpp)
|
||||
boost_test(TYPE run SOURCES multi_storage_test.cpp)
|
||||
boost_test(TYPE run SOURCES storage_adaptor_test.cpp)
|
||||
boost_test(TYPE run SOURCES unlimited_storage_test.cpp)
|
||||
boost_test(TYPE run SOURCES utility_test.cpp)
|
||||
|
@ -84,6 +84,7 @@ alias cxx14 :
|
||||
[ run histogram_operators_test.cpp ]
|
||||
[ run histogram_test.cpp ]
|
||||
[ run indexed_test.cpp ]
|
||||
[ run multi_storage_test.cpp ]
|
||||
[ run storage_adaptor_test.cpp ]
|
||||
[ run unlimited_storage_test.cpp ]
|
||||
[ run utility_test.cpp ]
|
||||
|
35
test/multi_storage_test.cpp
Normal file
35
test/multi_storage_test.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2022 Hans Dembinski
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/histogram/accumulators/sum.hpp>
|
||||
#include <boost/histogram/multi_storage.hpp>
|
||||
#include "throw_exception.hpp"
|
||||
|
||||
using namespace boost::histogram;
|
||||
|
||||
template <class T>
|
||||
void test() {
|
||||
using M = multi_storage<T>;
|
||||
|
||||
M m(2);
|
||||
|
||||
BOOST_TEST_EQ(m.width(), 2);
|
||||
BOOST_TEST_EQ(m.size(), 0);
|
||||
|
||||
m.reset(3);
|
||||
|
||||
BOOST_TEST_EQ(m.width(), 2);
|
||||
BOOST_TEST_EQ(m.size(), 3);
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
test<double>();
|
||||
test<accumulators::sum<double>>();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user