mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-12 13:41:48 +00:00
getting rid of buffer.hpp again, better operator+= for dynamic_storage, no move from static_storage
This commit is contained in:
parent
65a32b3630
commit
5f23c006a4
@ -1,250 +0,0 @@
|
|||||||
// Copyright 2015-2016 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_DETAIL_BUFFER_HPP_
|
|
||||||
#define _BOOST_HISTOGRAM_DETAIL_BUFFER_HPP_
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <new> // for bad_alloc exception
|
|
||||||
#include <boost/mpl/map.hpp>
|
|
||||||
#include <boost/mpl/pair.hpp>
|
|
||||||
#include <boost/mpl/int.hpp>
|
|
||||||
#include <boost/mpl/at.hpp>
|
|
||||||
#include <boost/histogram/detail/weight.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace histogram {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
using type_to_int = mpl::map<
|
|
||||||
mpl::pair<int8_t, mpl::int_<1>>,
|
|
||||||
mpl::pair<int16_t, mpl::int_<2>>,
|
|
||||||
mpl::pair<int32_t, mpl::int_<3>>,
|
|
||||||
mpl::pair<int64_t, mpl::int_<4>>,
|
|
||||||
mpl::pair<uint8_t, mpl::int_<1>>,
|
|
||||||
mpl::pair<uint16_t, mpl::int_<2>>,
|
|
||||||
mpl::pair<uint32_t, mpl::int_<3>>,
|
|
||||||
mpl::pair<uint64_t, mpl::int_<4>>,
|
|
||||||
mpl::pair<weight_t, mpl::int_<6>>
|
|
||||||
>;
|
|
||||||
|
|
||||||
using int_to_type = mpl::map<
|
|
||||||
mpl::pair<mpl::int_<1>, uint8_t>,
|
|
||||||
mpl::pair<mpl::int_<2>, uint16_t>,
|
|
||||||
mpl::pair<mpl::int_<3>, uint32_t>,
|
|
||||||
mpl::pair<mpl::int_<4>, uint64_t>,
|
|
||||||
mpl::pair<mpl::int_<6>, weight_t>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using next_storage_type =
|
|
||||||
typename mpl::at<int_to_type,
|
|
||||||
typename mpl::next<
|
|
||||||
typename mpl::at<type_to_int, T>::type
|
|
||||||
>::type
|
|
||||||
>::type;
|
|
||||||
|
|
||||||
class buffer {
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit
|
|
||||||
buffer(std::size_t s = 0) :
|
|
||||||
type_(),
|
|
||||||
size_(s),
|
|
||||||
ptr_(nullptr)
|
|
||||||
{}
|
|
||||||
|
|
||||||
buffer(const buffer& o) :
|
|
||||||
type_(o.type_), size_(o.size_), ptr_(nullptr)
|
|
||||||
{
|
|
||||||
realloc(depth());
|
|
||||||
std::copy(static_cast<const char*>(o.ptr_),
|
|
||||||
static_cast<const char*>(o.ptr_) + size() * depth(),
|
|
||||||
static_cast<char*>(ptr_));
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer& operator=(const buffer& o)
|
|
||||||
{
|
|
||||||
if (this != &o) {
|
|
||||||
if (size_ != o.size_ || type_ != o.type_) {
|
|
||||||
size_ = o.size_;
|
|
||||||
type_ = o.type_;
|
|
||||||
realloc(depth());
|
|
||||||
}
|
|
||||||
std::copy(static_cast<const char*>(o.ptr_),
|
|
||||||
static_cast<const char*>(o.ptr_) + size() * depth(),
|
|
||||||
static_cast<char*>(ptr_));
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer(buffer&& o) :
|
|
||||||
type_(o.type_),
|
|
||||||
size_(o.size_),
|
|
||||||
ptr_(o.ptr_)
|
|
||||||
{
|
|
||||||
o.size_ = 0;
|
|
||||||
o.type_ = type();
|
|
||||||
o.ptr_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer& operator=(buffer&& o)
|
|
||||||
{
|
|
||||||
if (this != &o) {
|
|
||||||
std::free(ptr_);
|
|
||||||
type_ = o.type_;
|
|
||||||
size_ = o.size_;
|
|
||||||
ptr_ = o.ptr_;
|
|
||||||
o.type_ = type();
|
|
||||||
o.size_ = 0;
|
|
||||||
o.ptr_ = nullptr;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, template<typename> class Storage>
|
|
||||||
buffer(const Storage<T>& o) :
|
|
||||||
size_(o.size()),
|
|
||||||
ptr_(nullptr)
|
|
||||||
{
|
|
||||||
using U = typename mpl::at<
|
|
||||||
int_to_type,
|
|
||||||
typename mpl::at<type_to_int, T>::type
|
|
||||||
>::type;
|
|
||||||
realloc(sizeof(U));
|
|
||||||
std::copy(o.data_, o.data_ + size_, &at<U>(0));
|
|
||||||
type_.set<U>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, template<typename> class Storage>
|
|
||||||
buffer& operator=(const Storage<T>& o) {
|
|
||||||
size_ = o.size();
|
|
||||||
using U = typename mpl::at<
|
|
||||||
int_to_type,
|
|
||||||
typename mpl::at<type_to_int, T>::type
|
|
||||||
>::type;
|
|
||||||
realloc(sizeof(U));
|
|
||||||
std::copy(o.data_, o.data_ + size_, &at<T>(0));
|
|
||||||
type_.set<U>();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, template<typename> class Storage>
|
|
||||||
buffer(Storage<T>&& o) :
|
|
||||||
size_(o.size_),
|
|
||||||
ptr_(const_cast<void*>(o.data_))
|
|
||||||
{
|
|
||||||
using U = typename mpl::at<
|
|
||||||
int_to_type,
|
|
||||||
typename mpl::at<type_to_int, T>::type
|
|
||||||
>::type;
|
|
||||||
type_.set<U>();
|
|
||||||
o.size_ = 0;
|
|
||||||
o.data_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, template<typename> class Storage>
|
|
||||||
buffer& operator=(Storage<T>&& o)
|
|
||||||
{
|
|
||||||
using U = typename mpl::at<
|
|
||||||
int_to_type,
|
|
||||||
typename mpl::at<type_to_int, T>::type
|
|
||||||
>::type;
|
|
||||||
std::free(ptr_);
|
|
||||||
size_ = o.size_;
|
|
||||||
ptr_ = static_cast<void*>(o.data_);
|
|
||||||
type_.set<U>();
|
|
||||||
o.size_ = 0;
|
|
||||||
o.data_ = nullptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~buffer() { std::free(ptr_); }
|
|
||||||
|
|
||||||
std::size_t size() const { return size_; }
|
|
||||||
unsigned id() const { return type_.id_; }
|
|
||||||
unsigned depth() const { return type_.depth_; }
|
|
||||||
const void* data() const { return ptr_; }
|
|
||||||
|
|
||||||
bool operator==(const buffer& o) const {
|
|
||||||
return size_ == o.size_ &&
|
|
||||||
type_.id_ == o.type_.id_ &&
|
|
||||||
std::equal(static_cast<char*>(ptr_),
|
|
||||||
static_cast<char*>(ptr_) + size_ * depth(),
|
|
||||||
static_cast<char*>(o.ptr_));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T,
|
|
||||||
typename U = next_storage_type<T>>
|
|
||||||
void grow() {
|
|
||||||
static_assert(sizeof(U) >= sizeof(T), "U must be as large or larger than T");
|
|
||||||
realloc(sizeof(U));
|
|
||||||
std::copy_backward(&at<T>(0), &at<T>(size_), &at<U>(size_));
|
|
||||||
type_.set<U>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void wconvert()
|
|
||||||
{
|
|
||||||
switch (type_.id_) {
|
|
||||||
case 0: initialize<weight_t>(); break;
|
|
||||||
case 1: grow<uint8_t, weight_t> (); break;
|
|
||||||
case 2: grow<uint16_t, weight_t>(); break;
|
|
||||||
case 3: grow<uint32_t, weight_t>(); break;
|
|
||||||
case 4: grow<uint64_t, weight_t>(); break;
|
|
||||||
case 6: /* do nothing */ break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void initialize() {
|
|
||||||
type_.set<T>();
|
|
||||||
ptr_ = nullptr;
|
|
||||||
realloc(sizeof(T));
|
|
||||||
std::fill(&at<T>(0), &at<T>(size_), T(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void realloc(unsigned d)
|
|
||||||
{
|
|
||||||
ptr_ = std::realloc(ptr_, size_ * d);
|
|
||||||
if (!ptr_ && (size_ * d > 0))
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T& at(std::size_t i) { return static_cast<T*>(ptr_)[i]; }
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
const T& at(std::size_t i) const { return static_cast<const T*>(ptr_)[i]; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct type {
|
|
||||||
char id_, depth_;
|
|
||||||
type() : id_(0), depth_(0) {}
|
|
||||||
type(const type&) = default;
|
|
||||||
type& operator=(const type&) = default;
|
|
||||||
template <typename T>
|
|
||||||
void set() {
|
|
||||||
id_ = mpl::at<type_to_int, T>::type::value;
|
|
||||||
depth_ = sizeof(T);
|
|
||||||
}
|
|
||||||
bool operator==(const type& o) const { return id_ == o.id_; }
|
|
||||||
bool operator!=(const type& o) const { return id_ != o.id_; }
|
|
||||||
};
|
|
||||||
|
|
||||||
type type_;
|
|
||||||
std::size_t size_;
|
|
||||||
void* ptr_;
|
|
||||||
|
|
||||||
template <class Archive>
|
|
||||||
friend void serialize(Archive&, buffer&, unsigned);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -7,30 +7,35 @@
|
|||||||
#ifndef _BOOST_HISTOGRAM_DETAIL_WEIGHT_HPP_
|
#ifndef _BOOST_HISTOGRAM_DETAIL_WEIGHT_HPP_
|
||||||
#define _BOOST_HISTOGRAM_DETAIL_WEIGHT_HPP_
|
#define _BOOST_HISTOGRAM_DETAIL_WEIGHT_HPP_
|
||||||
|
|
||||||
|
#include <boost/operators.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace histogram {
|
namespace histogram {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
/// Used by nstore to hold a sum of weighted counts and a variance estimate
|
/// Used by nstore to hold a sum of weighted counts and a variance estimate
|
||||||
struct weight_t {
|
struct weight_t
|
||||||
|
: boost::operators<weight_t>
|
||||||
|
{
|
||||||
double w, w2;
|
double w, w2;
|
||||||
weight_t() = default;
|
weight_t() = default;
|
||||||
weight_t(const weight_t&) = default;
|
weight_t(const weight_t&) = default;
|
||||||
weight_t(weight_t&&) = default;
|
weight_t(weight_t&&) = default;
|
||||||
weight_t& operator=(const weight_t&) = default;
|
weight_t& operator=(const weight_t&) = default;
|
||||||
weight_t& operator=(weight_t&&) = default;
|
weight_t& operator=(weight_t&&) = default;
|
||||||
|
|
||||||
weight_t& operator+=(const weight_t& o)
|
weight_t& operator+=(const weight_t& o)
|
||||||
{ w += o.w; w2 += o.w2; return *this; }
|
{ w += o.w; w2 += o.w2; return *this; }
|
||||||
weight_t& operator++()
|
weight_t& operator++()
|
||||||
{ ++w; ++w2; return *this; }
|
{ ++w; ++w2; return *this; }
|
||||||
bool operator==(const weight_t& o) const
|
bool operator==(const weight_t& o) const
|
||||||
{ return w == o.w && w2 == o.w2; }
|
{ return w == o.w && w2 == o.w2; }
|
||||||
bool operator!=(const weight_t& o) const
|
|
||||||
{ return !operator==(o); }
|
|
||||||
weight_t& add_weight(double v)
|
weight_t& add_weight(double v)
|
||||||
{ w += v; w2 += v*v; return *this; }
|
{ w += v; w2 += v*v; return *this; }
|
||||||
|
|
||||||
explicit weight_t(int v) : w(v), w2(v) {}
|
template <typename T>
|
||||||
|
explicit weight_t(const T& t) : w(static_cast<double>(t)), w2(w) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
weight_t& operator=(T v)
|
weight_t& operator=(T v)
|
||||||
|
@ -8,11 +8,17 @@
|
|||||||
#define _BOOST_HISTOGRAM_DYNAMIC_STORAGE_HPP_
|
#define _BOOST_HISTOGRAM_DYNAMIC_STORAGE_HPP_
|
||||||
|
|
||||||
#include <boost/histogram/detail/weight.hpp>
|
#include <boost/histogram/detail/weight.hpp>
|
||||||
#include <boost/histogram/detail/buffer.hpp>
|
|
||||||
#include <boost/histogram/detail/mpl.hpp>
|
#include <boost/histogram/detail/mpl.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/mpl/map.hpp>
|
||||||
|
#include <boost/mpl/pair.hpp>
|
||||||
|
#include <boost/mpl/int.hpp>
|
||||||
|
#include <boost/mpl/at.hpp>
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <cstdlib> // malloc/free
|
||||||
|
#include <new> // for bad_alloc exception
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@ -20,56 +26,253 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace histogram {
|
namespace histogram {
|
||||||
|
|
||||||
namespace {
|
namespace detail {
|
||||||
|
|
||||||
static_assert(std::is_pod<detail::weight_t>::value, "weight_t must be POD");
|
static_assert(std::is_pod<weight_t>::value, "weight_t must be POD");
|
||||||
|
|
||||||
|
using type_to_int = mpl::map<
|
||||||
|
mpl::pair<weight_t, mpl::int_<-1>>,
|
||||||
|
|
||||||
|
mpl::pair<int8_t, mpl::int_<1>>,
|
||||||
|
mpl::pair<int16_t, mpl::int_<2>>,
|
||||||
|
mpl::pair<int32_t, mpl::int_<3>>,
|
||||||
|
mpl::pair<int64_t, mpl::int_<4>>,
|
||||||
|
|
||||||
|
mpl::pair<uint8_t, mpl::int_<1>>,
|
||||||
|
mpl::pair<uint16_t, mpl::int_<2>>,
|
||||||
|
mpl::pair<uint32_t, mpl::int_<3>>,
|
||||||
|
mpl::pair<uint64_t, mpl::int_<4>>
|
||||||
|
>;
|
||||||
|
|
||||||
|
using int_to_type = mpl::map<
|
||||||
|
mpl::pair<mpl::int_<-1>, weight_t>,
|
||||||
|
mpl::pair<mpl::int_<1>, uint8_t>,
|
||||||
|
mpl::pair<mpl::int_<2>, uint16_t>,
|
||||||
|
mpl::pair<mpl::int_<3>, uint32_t>,
|
||||||
|
mpl::pair<mpl::int_<4>, uint64_t>
|
||||||
|
>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void increase_impl(detail::buffer& buf, std::size_t i) {
|
using storage_type =
|
||||||
auto& b = buf.at<T>(i);
|
typename mpl::at<
|
||||||
if (b < std::numeric_limits<T>::max())
|
detail::int_to_type,
|
||||||
++b;
|
typename mpl::at<
|
||||||
|
detail::type_to_int, T
|
||||||
|
>::type
|
||||||
|
>::type;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using next_storage_type =
|
||||||
|
typename mpl::at<int_to_type,
|
||||||
|
typename mpl::next<
|
||||||
|
typename mpl::at<type_to_int, T>::type
|
||||||
|
>::type
|
||||||
|
>::type;
|
||||||
|
|
||||||
|
struct buffer
|
||||||
|
{
|
||||||
|
explicit buffer(std::size_t s = 0) :
|
||||||
|
size_(s),
|
||||||
|
ptr_(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
buffer(const buffer& o) :
|
||||||
|
type_(o.type_), size_(o.size_), ptr_(nullptr)
|
||||||
|
{
|
||||||
|
realloc(type_.depth_);
|
||||||
|
std::copy(static_cast<const char*>(o.ptr_),
|
||||||
|
static_cast<const char*>(o.ptr_) + size_ * type_.depth_,
|
||||||
|
static_cast<char*>(ptr_));
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer& operator=(const buffer& o)
|
||||||
|
{
|
||||||
|
if (this != &o) {
|
||||||
|
if (size_ != o.size_ || type_.id_ != o.type_.id_) {
|
||||||
|
size_ = o.size_;
|
||||||
|
type_ = o.type_;
|
||||||
|
realloc(type_.depth_);
|
||||||
|
}
|
||||||
|
std::copy(static_cast<const char*>(o.ptr_),
|
||||||
|
static_cast<const char*>(o.ptr_) + size_ * type_.depth_,
|
||||||
|
static_cast<char*>(ptr_));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer(buffer&& o) :
|
||||||
|
type_(o.type_),
|
||||||
|
size_(o.size_),
|
||||||
|
ptr_(o.ptr_)
|
||||||
|
{
|
||||||
|
o.size_ = 0;
|
||||||
|
o.type_ = type();
|
||||||
|
o.ptr_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer& operator=(buffer&& o)
|
||||||
|
{
|
||||||
|
if (this != &o) {
|
||||||
|
destroy_any();
|
||||||
|
type_ = o.type_;
|
||||||
|
size_ = o.size_;
|
||||||
|
ptr_ = o.ptr_;
|
||||||
|
o.type_ = type();
|
||||||
|
o.size_ = 0;
|
||||||
|
o.ptr_ = nullptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~buffer() { destroy_any(); }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void create() {
|
||||||
|
type_.set<T>();
|
||||||
|
ptr_ = std::malloc(size_ * sizeof(T));
|
||||||
|
new (ptr_) T[size_];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void destroy() {
|
||||||
|
std::free(ptr_);
|
||||||
|
ptr_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_any() {
|
||||||
|
switch (type_.id_) {
|
||||||
|
case -1: destroy<weight_t>(); break;
|
||||||
|
case 0: /* do nothing */ break;
|
||||||
|
case 1: destroy<uint8_t>(); break;
|
||||||
|
case 2: destroy<uint16_t>(); break;
|
||||||
|
case 3: destroy<uint32_t>(); break;
|
||||||
|
case 4: destroy<uint64_t>(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
typename U = next_storage_type<T>>
|
||||||
|
void grow() {
|
||||||
|
static_assert(sizeof(U) >= sizeof(T), "U must be as large or larger than T");
|
||||||
|
realloc(sizeof(U));
|
||||||
|
std::copy_backward(&at<T>(0), &at<T>(size_), &at<U>(size_));
|
||||||
|
type_.set<U>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wconvert()
|
||||||
|
{
|
||||||
|
switch (type_.id_) {
|
||||||
|
case -1: /* do nothing */ break;
|
||||||
|
case 0: initialize<weight_t>(); break;
|
||||||
|
case 1: grow<uint8_t, weight_t> (); break;
|
||||||
|
case 2: grow<uint16_t, weight_t>(); break;
|
||||||
|
case 3: grow<uint32_t, weight_t>(); break;
|
||||||
|
case 4: grow<uint64_t, weight_t>(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void initialize() {
|
||||||
|
type_.set<T>();
|
||||||
|
ptr_ = nullptr;
|
||||||
|
realloc(sizeof(T));
|
||||||
|
std::fill(&at<T>(0), &at<T>(size_), T(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void realloc(unsigned d)
|
||||||
|
{
|
||||||
|
ptr_ = std::realloc(ptr_, size_ * d);
|
||||||
|
if (!ptr_ && (size_ * d > 0))
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T& at(std::size_t i) { return static_cast<T*>(ptr_)[i]; }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const T& at(std::size_t i) const { return static_cast<const T*>(ptr_)[i]; }
|
||||||
|
|
||||||
|
struct type {
|
||||||
|
char id_ = 0, depth_ = 0;
|
||||||
|
template <typename T>
|
||||||
|
void set() {
|
||||||
|
id_ = mpl::at<type_to_int, T>::type::value;
|
||||||
|
depth_ = sizeof(T);
|
||||||
|
}
|
||||||
|
} type_;
|
||||||
|
std::size_t size_;
|
||||||
|
void* ptr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void increase_impl(buffer& b, std::size_t i) {
|
||||||
|
auto& bi = b.at<T>(i);
|
||||||
|
if (bi < std::numeric_limits<T>::max())
|
||||||
|
++bi;
|
||||||
else {
|
else {
|
||||||
buf.grow<T>();
|
b.grow<T>();
|
||||||
using U = detail::next_storage_type<T>;
|
using U = detail::next_storage_type<T>;
|
||||||
auto& b = buf.at<U>(i);
|
++b.at<U>(i);
|
||||||
++b;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void increase_impl<uint64_t>(detail::buffer& buf, std::size_t i) {
|
void increase_impl<uint64_t>(buffer& b, std::size_t i) {
|
||||||
auto& b = buf.at<uint64_t>(i);
|
auto& bi = b.at<uint64_t>(i);
|
||||||
if (b < std::numeric_limits<uint64_t>::max())
|
if (bi < std::numeric_limits<uint64_t>::max())
|
||||||
++b;
|
++bi;
|
||||||
else
|
else
|
||||||
throw std::overflow_error("histogram overflow");
|
throw std::overflow_error("histogram overflow");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename TO>
|
||||||
void add_impl(detail::buffer& buf, std::size_t i, uint64_t o) {
|
struct add_one_impl {
|
||||||
auto& b = buf.at<T>(i);
|
static void apply(buffer& b, std::size_t i, const TO& o) {
|
||||||
if (static_cast<T>(std::numeric_limits<T>::max() - b) >= o)
|
auto& bi = b.at<T>(i);
|
||||||
b += o;
|
if (static_cast<T>(std::numeric_limits<T>::max() - bi) >= o)
|
||||||
else {
|
bi += o;
|
||||||
buf.grow<T>();
|
else {
|
||||||
add_impl<detail::next_storage_type<T>>(buf, i, o);
|
b.grow<T>();
|
||||||
|
add_one_impl<detail::next_storage_type<T>, TO>::apply(b, i, o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TO>
|
||||||
|
struct add_one_impl<uint64_t, TO> {
|
||||||
|
static void apply(buffer& b, std::size_t i, const TO& o) {
|
||||||
|
auto& bi = b.at<uint64_t>(i);
|
||||||
|
if (static_cast<uint64_t>(std::numeric_limits<uint64_t>::max() - bi) >= o)
|
||||||
|
bi += o;
|
||||||
|
else
|
||||||
|
throw std::overflow_error("histogram overflow");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TO>
|
||||||
|
void add_impl(buffer& b, const buffer& o) {
|
||||||
|
for (decltype(b.size_) i = 0; i < b.size_; ++i)
|
||||||
|
switch (b.type_.id_) {
|
||||||
|
case -1: b.at<weight_t>(i) += o.at<TO>(i); break;
|
||||||
|
case 0: b.initialize<uint8_t>(); // fall through
|
||||||
|
case 1: add_one_impl<uint8_t, TO>::apply(b, i, o.at<TO>(i)); break;
|
||||||
|
case 2: add_one_impl<uint16_t, TO>::apply(b, i, o.at<TO>(i)); break;
|
||||||
|
case 3: add_one_impl<uint32_t, TO>::apply(b, i, o.at<TO>(i)); break;
|
||||||
|
case 4: add_one_impl<uint64_t, TO>::apply(b, i, o.at<TO>(i)); break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void add_impl<uint64_t>(detail::buffer& buf, std::size_t i, uint64_t o) {
|
void add_impl<weight_t>(buffer& b, const buffer& o) {
|
||||||
auto& b = buf.at<uint64_t>(i);
|
b.wconvert();
|
||||||
if (static_cast<uint64_t>(std::numeric_limits<uint64_t>::max() - b) >= o)
|
for (decltype(b.size_) i = 0; i < b.size_; ++i)
|
||||||
b += o;
|
b.at<weight_t>(i) += o.at<weight_t>(i);
|
||||||
else
|
|
||||||
throw std::overflow_error("histogram overflow");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class dynamic_storage {
|
} // NS detail
|
||||||
using weight_t = detail::weight_t;
|
|
||||||
|
|
||||||
|
class dynamic_storage
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
using value_t = double;
|
using value_t = double;
|
||||||
using variance_t = double;
|
using variance_t = double;
|
||||||
@ -81,45 +284,37 @@ public:
|
|||||||
|
|
||||||
dynamic_storage() = default;
|
dynamic_storage() = default;
|
||||||
dynamic_storage(const dynamic_storage&) = default;
|
dynamic_storage(const dynamic_storage&) = default;
|
||||||
dynamic_storage(dynamic_storage&&) = default;
|
|
||||||
dynamic_storage& operator=(const dynamic_storage&) = default;
|
dynamic_storage& operator=(const dynamic_storage&) = default;
|
||||||
|
dynamic_storage(dynamic_storage&&) = default;
|
||||||
dynamic_storage& operator=(dynamic_storage&&) = default;
|
dynamic_storage& operator=(dynamic_storage&&) = default;
|
||||||
|
|
||||||
template <typename T,
|
template <typename T,
|
||||||
template <typename> class Storage,
|
template <typename> class Storage,
|
||||||
typename = detail::is_standard_integral<T>>
|
typename = detail::is_standard_integral<T>>
|
||||||
dynamic_storage(const Storage<T>& o) :
|
dynamic_storage(const Storage<T>& o) :
|
||||||
buffer_(o)
|
buffer_(o.size())
|
||||||
{}
|
{
|
||||||
|
using U = detail::storage_type<T>;
|
||||||
|
buffer_.create<U>();
|
||||||
|
std::copy(o.data(), o.data() + buffer_.size_, &buffer_.at<U>(0));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T,
|
template <typename T,
|
||||||
template <typename> class Storage,
|
template <typename> class Storage,
|
||||||
typename = detail::is_standard_integral<T>>
|
typename = detail::is_standard_integral<T>>
|
||||||
dynamic_storage& operator=(const Storage<T>& o)
|
dynamic_storage& operator=(const Storage<T>& o)
|
||||||
{
|
{
|
||||||
buffer_ = o;
|
buffer_.destroy_any();
|
||||||
|
buffer_.size_ = o.size();
|
||||||
|
using U = detail::storage_type<T>;
|
||||||
|
buffer_.create<U>();
|
||||||
|
std::copy(o.data(), o.data() + buffer_.size_, &buffer_.at<U>(0));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T,
|
std::size_t size() const { return buffer_.size_; }
|
||||||
template <typename> class Storage,
|
unsigned depth() const { return buffer_.type_.depth_; }
|
||||||
typename = detail::is_standard_integral<T>>
|
const void* data() const { return buffer_.ptr_; }
|
||||||
dynamic_storage(Storage<T>&& o) :
|
|
||||||
buffer_(std::move(o))
|
|
||||||
{}
|
|
||||||
|
|
||||||
template <typename T,
|
|
||||||
template <typename> class Storage,
|
|
||||||
typename = detail::is_standard_integral<T>>
|
|
||||||
dynamic_storage& operator=(Storage<T>&& o)
|
|
||||||
{
|
|
||||||
buffer_ = std::move(o);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t size() const { return buffer_.size(); }
|
|
||||||
unsigned depth() const { return buffer_.depth(); }
|
|
||||||
const void* data() const { return buffer_.data(); }
|
|
||||||
void increase(std::size_t i);
|
void increase(std::size_t i);
|
||||||
void increase(std::size_t i, double w);
|
void increase(std::size_t i, double w);
|
||||||
value_t value(std::size_t i) const;
|
value_t value(std::size_t i) const;
|
||||||
@ -136,13 +331,13 @@ private:
|
|||||||
inline
|
inline
|
||||||
void dynamic_storage::increase(std::size_t i)
|
void dynamic_storage::increase(std::size_t i)
|
||||||
{
|
{
|
||||||
switch (buffer_.id()) {
|
switch (buffer_.type_.id_) {
|
||||||
|
case -1: ++(buffer_.at<detail::weight_t>(i)); break;
|
||||||
case 0: buffer_.initialize<uint8_t>(); // and fall through
|
case 0: buffer_.initialize<uint8_t>(); // and fall through
|
||||||
case 1: increase_impl<uint8_t> (buffer_, i); break;
|
case 1: detail::increase_impl<uint8_t> (buffer_, i); break;
|
||||||
case 2: increase_impl<uint16_t>(buffer_, i); break;
|
case 2: detail::increase_impl<uint16_t>(buffer_, i); break;
|
||||||
case 3: increase_impl<uint32_t>(buffer_, i); break;
|
case 3: detail::increase_impl<uint32_t>(buffer_, i); break;
|
||||||
case 4: increase_impl<uint64_t>(buffer_, i); break;
|
case 4: detail::increase_impl<uint64_t>(buffer_, i); break;
|
||||||
case 6: ++(buffer_.at<weight_t>(i)); break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,39 +345,19 @@ inline
|
|||||||
void dynamic_storage::increase(std::size_t i, double w)
|
void dynamic_storage::increase(std::size_t i, double w)
|
||||||
{
|
{
|
||||||
buffer_.wconvert();
|
buffer_.wconvert();
|
||||||
buffer_.at<weight_t>(i).add_weight(w);
|
buffer_.at<detail::weight_t>(i).add_weight(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
dynamic_storage& dynamic_storage::operator+=(const dynamic_storage& o)
|
dynamic_storage& dynamic_storage::operator+=(const dynamic_storage& o)
|
||||||
{
|
{
|
||||||
if (o.depth()) {
|
switch (o.buffer_.type_.id_) {
|
||||||
if (o.buffer_.id() == 6) {
|
case -1: detail::add_impl<detail::weight_t>(buffer_, o.buffer_); break;
|
||||||
buffer_.wconvert();
|
case 0: /* do nothing */ break;
|
||||||
for (std::size_t i = 0; i < size(); ++i)
|
case 1: detail::add_impl<uint8_t>(buffer_, o.buffer_); break;
|
||||||
buffer_.at<weight_t>(i) += o.buffer_.at<weight_t>(i);
|
case 2: detail::add_impl<uint16_t>(buffer_, o.buffer_); break;
|
||||||
}
|
case 3: detail::add_impl<uint32_t>(buffer_, o.buffer_); break;
|
||||||
else {
|
case 4: detail::add_impl<uint64_t>(buffer_, o.buffer_); break;
|
||||||
auto i = size();
|
|
||||||
while (i--) {
|
|
||||||
uint64_t n = 0;
|
|
||||||
switch (o.buffer_.id()) {
|
|
||||||
/* case 0 is already excluded by the initial if statement */
|
|
||||||
case 1: n = o.buffer_.at<uint8_t> (i); break;
|
|
||||||
case 2: n = o.buffer_.at<uint16_t>(i); break;
|
|
||||||
case 3: n = o.buffer_.at<uint32_t>(i); break;
|
|
||||||
case 4: n = o.buffer_.at<uint64_t>(i); break;
|
|
||||||
}
|
|
||||||
switch (buffer_.id()) {
|
|
||||||
case 0: buffer_.initialize<uint8_t>(); // and fall through
|
|
||||||
case 1: add_impl<uint8_t> (buffer_, i, n); break;
|
|
||||||
case 2: add_impl<uint16_t>(buffer_, i, n); break;
|
|
||||||
case 3: add_impl<uint32_t>(buffer_, i, n); break;
|
|
||||||
case 4: add_impl<uint64_t>(buffer_, i, n); break;
|
|
||||||
case 6: buffer_.at<weight_t>(i) += n; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -190,13 +365,13 @@ dynamic_storage& dynamic_storage::operator+=(const dynamic_storage& o)
|
|||||||
inline
|
inline
|
||||||
dynamic_storage::value_t dynamic_storage::value(std::size_t i) const
|
dynamic_storage::value_t dynamic_storage::value(std::size_t i) const
|
||||||
{
|
{
|
||||||
switch (buffer_.id()) {
|
switch (buffer_.type_.id_) {
|
||||||
case 0: break;
|
case -1: return buffer_.at<detail::weight_t>(i).w;
|
||||||
|
case 0: /* do nothing */ break;
|
||||||
case 1: return buffer_.at<uint8_t> (i);
|
case 1: return buffer_.at<uint8_t> (i);
|
||||||
case 2: return buffer_.at<uint16_t>(i);
|
case 2: return buffer_.at<uint16_t>(i);
|
||||||
case 3: return buffer_.at<uint32_t>(i);
|
case 3: return buffer_.at<uint32_t>(i);
|
||||||
case 4: return buffer_.at<uint64_t>(i);
|
case 4: return buffer_.at<uint64_t>(i);
|
||||||
case 6: return buffer_.at<weight_t>(i).w;
|
|
||||||
}
|
}
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
@ -204,13 +379,13 @@ dynamic_storage::value_t dynamic_storage::value(std::size_t i) const
|
|||||||
inline
|
inline
|
||||||
dynamic_storage::variance_t dynamic_storage::variance(std::size_t i) const
|
dynamic_storage::variance_t dynamic_storage::variance(std::size_t i) const
|
||||||
{
|
{
|
||||||
switch (buffer_.id()) {
|
switch (buffer_.type_.id_) {
|
||||||
case 0: break;
|
case -1: return buffer_.at<detail::weight_t>(i).w2;
|
||||||
|
case 0: /* do nothing */ break;
|
||||||
case 1: return buffer_.at<uint8_t> (i);
|
case 1: return buffer_.at<uint8_t> (i);
|
||||||
case 2: return buffer_.at<uint16_t>(i);
|
case 2: return buffer_.at<uint16_t>(i);
|
||||||
case 3: return buffer_.at<uint32_t>(i);
|
case 3: return buffer_.at<uint32_t>(i);
|
||||||
case 4: return buffer_.at<uint64_t>(i);
|
case 4: return buffer_.at<uint64_t>(i);
|
||||||
case 6: return buffer_.at<weight_t>(i).w2;
|
|
||||||
}
|
}
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include <boost/histogram/dynamic_storage.hpp>
|
#include <boost/histogram/dynamic_storage.hpp>
|
||||||
#include <boost/histogram/detail/utility.hpp>
|
#include <boost/histogram/detail/utility.hpp>
|
||||||
#include <boost/histogram/detail/weight.hpp>
|
#include <boost/histogram/detail/weight.hpp>
|
||||||
#include <boost/histogram/detail/buffer.hpp>
|
|
||||||
#include <boost/histogram/detail/tiny_string.hpp>
|
#include <boost/histogram/detail/tiny_string.hpp>
|
||||||
#include <boost/serialization/variant.hpp>
|
#include <boost/serialization/variant.hpp>
|
||||||
#include <boost/serialization/vector.hpp>
|
#include <boost/serialization/vector.hpp>
|
||||||
@ -38,32 +37,6 @@ inline void serialize(Archive& ar, weight_t& wt, unsigned version)
|
|||||||
ar & wt.w2;
|
ar & wt.w2;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Archive>
|
|
||||||
inline void serialize(Archive& ar, buffer& buf, unsigned version)
|
|
||||||
{
|
|
||||||
ar & buf.size_;
|
|
||||||
ar & buf.type_.id_;
|
|
||||||
ar & buf.type_.depth_;
|
|
||||||
if (Archive::is_loading::value) {
|
|
||||||
buf.realloc(buf.depth());
|
|
||||||
// switch (buf.type_) {
|
|
||||||
// case 1: buf.create<uint8_t>(); break;
|
|
||||||
// case 2: buf.create<uint16_t>(); break;
|
|
||||||
// case 3: buf.create<uint32_t>(); break;
|
|
||||||
// case 4: buf.create<uint64_t>(); break;
|
|
||||||
// case 6: buf.create<weight_t>(); break;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
switch (buf.type_.id_) {
|
|
||||||
case 0: buf.ptr_ = nullptr; break;
|
|
||||||
case 1: ar & serialization::make_array(&buf.at<uint8_t>(0), buf.size_); break;
|
|
||||||
case 2: ar & serialization::make_array(&buf.at<uint16_t>(0), buf.size_); break;
|
|
||||||
case 3: ar & serialization::make_array(&buf.at<uint32_t>(0), buf.size_); break;
|
|
||||||
case 4: ar & serialization::make_array(&buf.at<uint64_t>(0), buf.size_); break;
|
|
||||||
case 6: ar & serialization::make_array(&buf.at<weight_t>(0), buf.size_); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
inline void serialize(Archive& ar, tiny_string& s, unsigned version)
|
inline void serialize(Archive& ar, tiny_string& s, unsigned version)
|
||||||
{
|
{
|
||||||
@ -91,7 +64,30 @@ inline void serialize(Archive& ar, static_storage<T> & store, unsigned version)
|
|||||||
template <class Archive>
|
template <class Archive>
|
||||||
inline void serialize(Archive& ar, dynamic_storage & store, unsigned version)
|
inline void serialize(Archive& ar, dynamic_storage & store, unsigned version)
|
||||||
{
|
{
|
||||||
ar & store.buffer_;
|
auto& b = store.buffer_;
|
||||||
|
if (Archive::is_loading::value)
|
||||||
|
b.destroy_any();
|
||||||
|
ar & b.size_;
|
||||||
|
ar & b.type_.id_;
|
||||||
|
ar & b.type_.depth_;
|
||||||
|
if (Archive::is_loading::value) {
|
||||||
|
switch (b.type_.id_) {
|
||||||
|
case -1: b.create<detail::weight_t>(); break;
|
||||||
|
case 0: b.ptr_ = nullptr; break;
|
||||||
|
case 1: b.create<uint8_t>(); break;
|
||||||
|
case 2: b.create<uint16_t>(); break;
|
||||||
|
case 3: b.create<uint32_t>(); break;
|
||||||
|
case 4: b.create<uint64_t>(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (b.type_.id_) {
|
||||||
|
case -1: ar & serialization::make_array(&b.at<detail::weight_t>(0), b.size_); break;
|
||||||
|
case 0: /* nothing to do */ break;
|
||||||
|
case 1: ar & serialization::make_array(&b.at<uint8_t>(0), b.size_); break;
|
||||||
|
case 2: ar & serialization::make_array(&b.at<uint16_t>(0), b.size_); break;
|
||||||
|
case 3: ar & serialization::make_array(&b.at<uint32_t>(0), b.size_); break;
|
||||||
|
case 4: ar & serialization::make_array(&b.at<uint64_t>(0), b.size_); break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace histogram {
|
namespace histogram {
|
||||||
|
|
||||||
namespace detail { class buffer; }
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class static_storage {
|
class static_storage {
|
||||||
public:
|
public:
|
||||||
@ -104,7 +102,7 @@ namespace histogram {
|
|||||||
|
|
||||||
std::size_t size() const { return size_; }
|
std::size_t size() const { return size_; }
|
||||||
constexpr unsigned depth() const { return sizeof(T); }
|
constexpr unsigned depth() const { return sizeof(T); }
|
||||||
const void* data() const { return static_cast<const void*>(data_); }
|
const T* data() const { return data_; }
|
||||||
void increase(std::size_t i) { ++(data_[i]); }
|
void increase(std::size_t i) { ++(data_[i]); }
|
||||||
value_t value(std::size_t i) const { return data_[i]; }
|
value_t value(std::size_t i) const { return data_[i]; }
|
||||||
variance_t variance(std::size_t i) const { return data_[i]; }
|
variance_t variance(std::size_t i) const { return data_[i]; }
|
||||||
@ -128,8 +126,6 @@ namespace histogram {
|
|||||||
data_ = new T[size_];
|
data_ = new T[size_];
|
||||||
}
|
}
|
||||||
|
|
||||||
friend detail::buffer;
|
|
||||||
|
|
||||||
template <typename Archive, typename U>
|
template <typename Archive, typename U>
|
||||||
friend void serialize(Archive&, static_storage<U>&, unsigned);
|
friend void serialize(Archive&, static_storage<U>&, unsigned);
|
||||||
};
|
};
|
||||||
|
@ -8,11 +8,40 @@
|
|||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
#include <boost/test/test_tools.hpp>
|
#include <boost/test/test_tools.hpp>
|
||||||
#include <boost/histogram/detail/utility.hpp>
|
#include <boost/histogram/detail/utility.hpp>
|
||||||
#include <boost/histogram/detail/buffer.hpp>
|
#include <boost/histogram/detail/weight.hpp>
|
||||||
#include <boost/histogram/detail/tiny_string.hpp>
|
#include <boost/histogram/detail/tiny_string.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
using namespace boost::histogram::detail;
|
using namespace boost::histogram::detail;
|
||||||
|
|
||||||
|
// bool operator==(const buffer& a, const buffer& b)
|
||||||
|
// {
|
||||||
|
// if (!(a.size() == b.size() &&
|
||||||
|
// a.id() == b.id() &&
|
||||||
|
// a.depth() == b.depth()))
|
||||||
|
// return false;
|
||||||
|
// switch (a.id()) {
|
||||||
|
// case -1: return std::equal(&a.at<weight_t>(0),
|
||||||
|
// &a.at<weight_t>(a.size()),
|
||||||
|
// &b.at<weight_t>(0));
|
||||||
|
// case 0: return true;
|
||||||
|
// case 1: return std::equal(&a.at<uint8_t>(0),
|
||||||
|
// &a.at<uint8_t>(a.size()),
|
||||||
|
// &b.at<uint8_t>(0));
|
||||||
|
// case 2: return std::equal(&a.at<uint16_t>(0),
|
||||||
|
// &a.at<uint16_t>(a.size()),
|
||||||
|
// &b.at<uint16_t>(0));
|
||||||
|
// case 3: return std::equal(&a.at<uint32_t>(0),
|
||||||
|
// &a.at<uint32_t>(a.size()),
|
||||||
|
// &b.at<uint32_t>(0));
|
||||||
|
// case 4: return std::equal(&a.at<uint64_t>(0),
|
||||||
|
// &a.at<uint64_t>(a.size()),
|
||||||
|
// &b.at<uint64_t>(0));
|
||||||
|
// }
|
||||||
|
// BOOST_ASSERT(!"never reach this");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(escape_0)
|
BOOST_AUTO_TEST_CASE(escape_0)
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
@ -34,99 +63,99 @@ BOOST_AUTO_TEST_CASE(escape_2)
|
|||||||
BOOST_CHECK_EQUAL(os.str(), std::string("'\\\'abc\\\''"));
|
BOOST_CHECK_EQUAL(os.str(), std::string("'\\\'abc\\\''"));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(buffer_ctor_and_get)
|
// BOOST_AUTO_TEST_CASE(buffer_ctor_and_get)
|
||||||
{
|
// {
|
||||||
auto a = buffer(3);
|
// auto a = buffer(3);
|
||||||
a.initialize<uint8_t>();
|
// a.initialize<uint8_t>();
|
||||||
BOOST_CHECK_EQUAL(a.size(), 3);
|
// BOOST_CHECK_EQUAL(a.size(), 3);
|
||||||
BOOST_CHECK_EQUAL(a.depth(), 1);
|
// BOOST_CHECK_EQUAL(a.depth(), 1);
|
||||||
a.at<uint8_t>(0) = 0;
|
// a.at<uint8_t>(0) = 0;
|
||||||
a.at<uint8_t>(1) = 1;
|
// a.at<uint8_t>(1) = 1;
|
||||||
a.at<uint8_t>(2) = 0;
|
// a.at<uint8_t>(2) = 0;
|
||||||
BOOST_CHECK_EQUAL(a.at<uint8_t>(0), 0);
|
// BOOST_CHECK_EQUAL(a.at<uint8_t>(0), 0);
|
||||||
BOOST_CHECK_EQUAL(a.at<uint8_t>(1), 1);
|
// BOOST_CHECK_EQUAL(a.at<uint8_t>(1), 1);
|
||||||
BOOST_CHECK_EQUAL(a.at<uint8_t>(2), 0);
|
// BOOST_CHECK_EQUAL(a.at<uint8_t>(2), 0);
|
||||||
BOOST_CHECK(a == a);
|
// BOOST_CHECK(a == a);
|
||||||
auto b = buffer(3);
|
// auto b = buffer(3);
|
||||||
b.initialize<uint8_t>();
|
// b.initialize<uint8_t>();
|
||||||
BOOST_CHECK(!(a == b));
|
// BOOST_CHECK(!(a == b));
|
||||||
auto c = buffer(1);
|
// auto c = buffer(1);
|
||||||
c.initialize<uint8_t>();
|
// c.initialize<uint8_t>();
|
||||||
BOOST_CHECK(!(a == c));
|
// BOOST_CHECK(!(a == c));
|
||||||
auto d = buffer();
|
// auto d = buffer();
|
||||||
BOOST_CHECK(!(a == d));
|
// BOOST_CHECK(!(a == d));
|
||||||
}
|
// }
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(buffer_copy_ctor)
|
// BOOST_AUTO_TEST_CASE(buffer_copy_ctor)
|
||||||
{
|
// {
|
||||||
auto a = buffer(3);
|
// auto a = buffer(3);
|
||||||
a.initialize<uint8_t>();
|
// a.initialize<uint8_t>();
|
||||||
a.at<uint8_t>(1) = 1;
|
// a.at<uint8_t>(1) = 1;
|
||||||
auto b = a;
|
// auto b = a;
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(0), 0);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(0), 0);
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(1), 1);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(1), 1);
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(2), 0);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(2), 0);
|
||||||
BOOST_CHECK(a == b);
|
// BOOST_CHECK(a == b);
|
||||||
}
|
// }
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(buffer_move_ctor)
|
// BOOST_AUTO_TEST_CASE(buffer_move_ctor)
|
||||||
{
|
// {
|
||||||
auto a = buffer(3);
|
// auto a = buffer(3);
|
||||||
a.initialize<uint8_t>();
|
// a.initialize<uint8_t>();
|
||||||
a.at<uint8_t>(1) = 1;
|
// a.at<uint8_t>(1) = 1;
|
||||||
auto b = std::move(a);
|
// auto b = std::move(a);
|
||||||
BOOST_CHECK_EQUAL(a.size(), 0);
|
// BOOST_CHECK_EQUAL(a.size(), 0);
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(0), 0);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(0), 0);
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(1), 1);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(1), 1);
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(2), 0);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(2), 0);
|
||||||
BOOST_CHECK(!(a == b));
|
// BOOST_CHECK(!(a == b));
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(buffer_copy_assign)
|
// BOOST_AUTO_TEST_CASE(buffer_copy_assign)
|
||||||
{
|
// {
|
||||||
auto a = buffer(3);
|
// auto a = buffer(3);
|
||||||
a.initialize<uint8_t>();
|
// a.initialize<uint8_t>();
|
||||||
a.at<uint8_t>(1) = 1;
|
// a.at<uint8_t>(1) = 1;
|
||||||
auto b = buffer(3);
|
// auto b = buffer(3);
|
||||||
b.initialize<uint8_t>();
|
// b.initialize<uint8_t>();
|
||||||
b = a;
|
// b = a;
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(0), 0);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(0), 0);
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(1), 1);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(1), 1);
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(2), 0);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(2), 0);
|
||||||
BOOST_CHECK(a == b);
|
// BOOST_CHECK(a == b);
|
||||||
}
|
// }
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(buffer_move_assign)
|
// BOOST_AUTO_TEST_CASE(buffer_move_assign)
|
||||||
{
|
// {
|
||||||
auto a = buffer(3);
|
// auto a = buffer(3);
|
||||||
a.initialize<uint8_t>();
|
// a.initialize<uint8_t>();
|
||||||
a.at<uint8_t>(1) = 1;
|
// a.at<uint8_t>(1) = 1;
|
||||||
auto b = buffer(3);
|
// auto b = buffer(3);
|
||||||
b.initialize<uint8_t>();
|
// b.initialize<uint8_t>();
|
||||||
b = std::move(a);
|
// b = std::move(a);
|
||||||
BOOST_CHECK_EQUAL(a.size(), 0);
|
// BOOST_CHECK_EQUAL(a.size(), 0);
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(0), 0);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(0), 0);
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(1), 1);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(1), 1);
|
||||||
BOOST_CHECK_EQUAL(b.at<uint8_t>(2), 0);
|
// BOOST_CHECK_EQUAL(b.at<uint8_t>(2), 0);
|
||||||
BOOST_CHECK(!(a == b));
|
// BOOST_CHECK(!(a == b));
|
||||||
}
|
// }
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(buffer_realloc)
|
// BOOST_AUTO_TEST_CASE(buffer_realloc)
|
||||||
{
|
// {
|
||||||
auto a = buffer(3);
|
// auto a = buffer(3);
|
||||||
a.initialize<uint8_t>();
|
// a.initialize<uint8_t>();
|
||||||
BOOST_CHECK_EQUAL(a.size(), 3);
|
// BOOST_CHECK_EQUAL(a.size(), 3);
|
||||||
a.at<uint8_t>(0) = 1;
|
// a.at<uint8_t>(0) = 1;
|
||||||
a.at<uint8_t>(1) = 2;
|
// a.at<uint8_t>(1) = 2;
|
||||||
a.at<uint8_t>(2) = 3;
|
// a.at<uint8_t>(2) = 3;
|
||||||
a.grow<uint8_t>();
|
// a.grow<uint8_t>();
|
||||||
BOOST_CHECK_EQUAL(a.size(), 3);
|
// BOOST_CHECK_EQUAL(a.size(), 3);
|
||||||
BOOST_CHECK_EQUAL(a.depth(), 2);
|
// BOOST_CHECK_EQUAL(a.depth(), 2);
|
||||||
BOOST_CHECK_EQUAL(a.at<int16_t>(0), 1);
|
// BOOST_CHECK_EQUAL(a.at<int16_t>(0), 1);
|
||||||
BOOST_CHECK_EQUAL(a.at<int16_t>(1), 2);
|
// BOOST_CHECK_EQUAL(a.at<int16_t>(1), 2);
|
||||||
BOOST_CHECK_EQUAL(a.at<int16_t>(2), 3);
|
// BOOST_CHECK_EQUAL(a.at<int16_t>(2), 3);
|
||||||
}
|
// }
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(tiny_string_test)
|
BOOST_AUTO_TEST_CASE(tiny_string_test)
|
||||||
{
|
{
|
||||||
|
@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(dynamic_storage_equality)
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void convert_static_storage_impl() {
|
void convert_static_storage_impl() {
|
||||||
dynamic_storage a(2), b(2), c(2);
|
dynamic_storage a(2), b(2);
|
||||||
static_storage<T> s(2);
|
static_storage<T> s(2);
|
||||||
a.increase(0);
|
a.increase(0);
|
||||||
b.increase(0, 1.0);
|
b.increase(0, 1.0);
|
||||||
@ -136,15 +136,17 @@ void convert_static_storage_impl() {
|
|||||||
BOOST_CHECK(s == b);
|
BOOST_CHECK(s == b);
|
||||||
a = dynamic_storage(2);
|
a = dynamic_storage(2);
|
||||||
b = dynamic_storage(2);
|
b = dynamic_storage(2);
|
||||||
|
BOOST_CHECK(a == b);
|
||||||
a += s;
|
a += s;
|
||||||
b += s;
|
|
||||||
BOOST_CHECK(a == s);
|
BOOST_CHECK(a == s);
|
||||||
BOOST_CHECK(s == a);
|
BOOST_CHECK(s == a);
|
||||||
BOOST_CHECK(b == s);
|
dynamic_storage c(s);
|
||||||
BOOST_CHECK(s == b);
|
BOOST_CHECK(c == s);
|
||||||
|
BOOST_CHECK(s == c);
|
||||||
dynamic_storage d;
|
dynamic_storage d;
|
||||||
d = std::move(s);
|
d = std::move(s); // cannot move, uses copy
|
||||||
BOOST_CHECK(a == d);
|
BOOST_CHECK(d == s);
|
||||||
|
BOOST_CHECK(s == d);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(convert_static_storage)
|
BOOST_AUTO_TEST_CASE(convert_static_storage)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user