mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-11 13:14:06 +00:00
wip
This commit is contained in:
parent
98f634e232
commit
78dbdd52e5
@ -31,7 +31,7 @@
|
|||||||
#include <boost/histogram/literals.hpp>
|
#include <boost/histogram/literals.hpp>
|
||||||
#include <boost/histogram/make_histogram.hpp>
|
#include <boost/histogram/make_histogram.hpp>
|
||||||
#include <boost/histogram/make_profile.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/storage_adaptor.hpp>
|
||||||
#include <boost/histogram/unlimited_storage.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")
|
PROPERTIES ENVIRONMENT "LANG=FOO;COLUMNS=20")
|
||||||
boost_test(TYPE run SOURCES histogram_test.cpp)
|
boost_test(TYPE run SOURCES histogram_test.cpp)
|
||||||
boost_test(TYPE run SOURCES indexed_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 storage_adaptor_test.cpp)
|
||||||
boost_test(TYPE run SOURCES unlimited_storage_test.cpp)
|
boost_test(TYPE run SOURCES unlimited_storage_test.cpp)
|
||||||
boost_test(TYPE run SOURCES utility_test.cpp)
|
boost_test(TYPE run SOURCES utility_test.cpp)
|
||||||
|
@ -84,6 +84,7 @@ alias cxx14 :
|
|||||||
[ run histogram_operators_test.cpp ]
|
[ run histogram_operators_test.cpp ]
|
||||||
[ run histogram_test.cpp ]
|
[ run histogram_test.cpp ]
|
||||||
[ run indexed_test.cpp ]
|
[ run indexed_test.cpp ]
|
||||||
|
[ run multi_storage_test.cpp ]
|
||||||
[ run storage_adaptor_test.cpp ]
|
[ run storage_adaptor_test.cpp ]
|
||||||
[ run unlimited_storage_test.cpp ]
|
[ run unlimited_storage_test.cpp ]
|
||||||
[ run utility_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