new feature, filling with weights

This commit is contained in:
Hans Dembinski 2016-04-09 16:31:16 -04:00
parent 14c7a282dc
commit 103fa6cf0a
14 changed files with 645 additions and 355 deletions

View File

@ -9,28 +9,30 @@ find_package(Boost 1.55 REQUIRED
COMPONENTS python iostreams serialization unit_test_framework)
find_package(PythonLibs)
find_package(Numpy) # optional
find_package(ROOT) # only used in one of the tests
include_directories(include ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
include_directories(include ${Boost_INCLUDE_DIRS})
add_definitions(-DBOOST_TEST_DYN_LINK) # for unit_test_framework
set(LIBRARIES stdc++ ${Boost_LIBRARIES})
if(Boost_PYTHON_FOUND)
if(Boost_PYTHON_FOUND AND PYTHONLIBS_FOUND)
set(USE_PYTHON True)
include_directories(${PYTHON_INCLUDE_DIRS})
LIST(APPEND LIBRARIES ${PYTHON_LIBRARIES})
endif()
add_definitions(-DUSE_PYTHON)
if(NUMPY_FOUND)
if(NUMPY_FOUND)
include_directories(${NUMPY_INCLUDE_DIR})
add_definitions(-DUSE_NUMPY)
endif()
endif()
# core library
add_library(histogram SHARED
src/axis.cpp
src/histogram_base.cpp
src/nhistogram.cpp
src/histogram.cpp
src/nstore.cpp
src/zero_suppression.cpp
# src/whistogram.cpp
)
target_link_libraries(histogram ${LIBRARIES})
@ -41,21 +43,24 @@ else()
target_compile_options(histogram PUBLIC "-O3 -fomit-frame-pointer -mtune=generic")
endif()
if(Boost_PYTHON_FOUND)
# python bindings
if(USE_PYTHON)
add_library(pyhistogram MODULE
src/python/module.cpp
src/python/histogram_base.cpp
src/python/nhistogram.cpp
src/python/histogram.cpp
)
target_link_libraries(pyhistogram histogram ${LIBRARIES})
set_target_properties(pyhistogram PROPERTIES OUTPUT_NAME "histogram" PREFIX "" SUFFIX ".so")
endif()
# examples
add_executable(sizeof
examples/sizeof.cpp
)
target_link_libraries(sizeof ${LIBRARIES})
find_package(ROOT) # only used in speed comparison
if(ROOT_FOUND)
add_executable(nhistogram_speed
examples/speed_vs_root.cpp)

View File

@ -1,4 +1,4 @@
#include <boost/histogram/nhistogram.hpp>
#include <boost/histogram/histogram.hpp>
#include <boost/histogram/axis.hpp>
#include <boost/random.hpp>
#include <boost/array.hpp>
@ -51,7 +51,7 @@ void compare_1d(unsigned n)
t = clock() - t;
best_root = std::min(best_root, double(t) / CLOCKS_PER_SEC);
nhistogram h(regular_axis(100, 0, 1));
histogram h(regular_axis(100, 0, 1));
t = clock();
for (unsigned i = 0; i < n; ++i)
h.fill(r[i]);
@ -80,7 +80,7 @@ void compare_3d(unsigned n)
t = clock() - t;
best_root = std::min(best_root, double(t) / CLOCKS_PER_SEC);
nhistogram h(regular_axis(100, 0, 1),
histogram h(regular_axis(100, 0, 1),
regular_axis(100, 0, 1),
regular_axis(100, 0, 1));
t = clock();
@ -118,7 +118,7 @@ void compare_6d(unsigned n)
t = clock() - t;
best_root = std::min(best_root, double(t) / CLOCKS_PER_SEC);
nhistogram h(regular_axis(10, 0, 1),
histogram h(regular_axis(10, 0, 1),
regular_axis(10, 0, 1),
regular_axis(10, 0, 1),
regular_axis(10, 0, 1),

View File

@ -1,10 +1,12 @@
#ifndef _BOOST_HISTOGRAM_NSTORE_HPP_
#define _BOOST_HISTOGRAM_NSTORE_HPP_
#ifndef _BOOST_HISTOGRAM_DETAIL_NSTORE_HPP_
#define _BOOST_HISTOGRAM_DETAIL_NSTORE_HPP_
#include <boost/histogram/detail/wtype.hpp>
#include <boost/histogram/detail/zero_suppression.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/array.hpp>
#include <boost/histogram/detail/zero_suppression.hpp>
#include <boost/cstdint.hpp>
#include <boost/assert.hpp>
#include <cstdlib>
#include <cstring>
#include <limits>
@ -20,7 +22,6 @@ class nstore {
public:
typedef uintptr_t size_type;
public:
nstore();
nstore(const nstore&);
nstore(size_type, unsigned d = sizeof(uint8_t));
@ -30,11 +31,12 @@ public:
nstore& operator+=(const nstore&);
bool operator==(const nstore&) const;
uint64_t read(size_type) const;
void write(size_type, uint64_t);
inline void increase(size_type i) {
switch (depth_) {
case sizeof(wtype): {
wtype& b = ((wtype*)buffer_)[i];
b += 1.0;
}
#define BOOST_HISTOGRAM_NSTORE_INC(T) \
case sizeof(T): { \
T& b = ((T*)buffer_)[i]; \
@ -51,6 +53,14 @@ public:
}
}
inline void increase(size_type i, double w) {
assert(depth_ == sizeof(wtype));
((wtype*)buffer_)[i] += w;
}
double value(size_type) const;
double variance(size_type) const;
const void* buffer() const { return buffer_; }
unsigned depth() const { return depth_; }
@ -62,8 +72,24 @@ private:
void create();
void destroy();
void grow();
void wconvert();
uint64_t max_count() const;
uint64_t max_count() const
{
switch (depth_) {
#define BOOST_HISTOGRAM_NSTORE_CASE(T) \
case sizeof(T): return std::numeric_limits<T>::max()
BOOST_HISTOGRAM_NSTORE_CASE(uint8_t);
BOOST_HISTOGRAM_NSTORE_CASE(uint16_t);
BOOST_HISTOGRAM_NSTORE_CASE(uint32_t);
BOOST_HISTOGRAM_NSTORE_CASE(uint64_t);
#undef BOOST_HISTOGRAM_NSTORE_CASE
default: assert(!"invalid depth");
}
return 0;
}
uint64_t ivalue(size_type) const;
friend class serialization::access;
template <class Archive>
@ -81,26 +107,50 @@ private:
throw std::bad_alloc();
if (Archive::is_saving::value) {
std::vector<char> buf;
if (zero_suppression_encode(buf, size_ * depth_,
(char*)buffer_, size_ * depth_)) {
bool is_zero_suppressed = true;
ar & is_zero_suppressed;
ar & buf;
} else {
bool is_zero_suppressed = false;
ar & is_zero_suppressed;
ar & serialization::make_array((char*)buffer_, size_ * depth_);
switch (depth_) {
#define BOOST_HISTOGRAM_NSTORE_SAVE(T) \
case sizeof(T): { \
std::vector<T> buf; \
if (zero_suppression_encode<T>(buf, (T*)buffer_, size_)) { \
bool is_zero_suppressed = true; \
ar & is_zero_suppressed; \
ar & buf; \
} else { \
bool is_zero_suppressed = false; \
ar & is_zero_suppressed; \
ar & serialization::make_array((T*)buffer_, size_); \
} \
} break
BOOST_HISTOGRAM_NSTORE_SAVE(uint8_t);
BOOST_HISTOGRAM_NSTORE_SAVE(uint16_t);
BOOST_HISTOGRAM_NSTORE_SAVE(uint32_t);
BOOST_HISTOGRAM_NSTORE_SAVE(uint64_t);
BOOST_HISTOGRAM_NSTORE_SAVE(wtype);
#undef BOOST_HISTOGRAM_NSTORE_SAVE
default: assert(!"invalid depth");
}
} else {
}
if (Archive::is_loading::value) {
bool is_zero_suppressed = false;
ar & is_zero_suppressed;
if (is_zero_suppressed) {
std::vector<char> buf;
ar & buf;
zero_suppression_decode((char*)buffer_, size_ * depth_, buf);
} else {
ar & serialization::make_array((char*)buffer_, size_ * depth_);
switch (depth_) {
#define BOOST_HISTOGRAM_NSTORE_LOAD(T) \
case sizeof(T): \
if (is_zero_suppressed) { \
std::vector<T> buf; \
ar & buf; \
zero_suppression_decode<T>((T*)buffer_, size_, buf); \
} else { \
ar & serialization::make_array((T*)buffer_, size_); \
} break
BOOST_HISTOGRAM_NSTORE_LOAD(uint8_t);
BOOST_HISTOGRAM_NSTORE_LOAD(uint16_t);
BOOST_HISTOGRAM_NSTORE_LOAD(uint32_t);
BOOST_HISTOGRAM_NSTORE_LOAD(uint64_t);
BOOST_HISTOGRAM_NSTORE_LOAD(wtype);
#undef BOOST_HISTOGRAM_NSTORE_LOAD
default: assert(!"invalid depth");
}
}
}

View File

@ -0,0 +1,47 @@
#ifndef _BOOST_HISTOGRAM_DETAIL_WTYPE_HPP_
#define _BOOST_HISTOGRAM_DETAIL_WTYPE_HPP_
#include <boost/cstdint.hpp>
#include <ostream>
namespace boost {
namespace histogram {
namespace detail {
struct wtype {
double w, w2;
wtype() : w(0), w2(0) {}
wtype(const wtype& o) : w(o.w), w2(o.w2) {}
wtype(uint64_t i) : w(i), w2(i) {}
wtype& operator+=(const wtype& o)
{ w += o.w; w2 += o.w2; return *this; }
wtype& operator+=(double v)
{ w += v; w2 += v*v; return *this; }
wtype& operator=(uint64_t i)
{ w = i; w2 = i; return *this; }
bool operator==(uint64_t i) const
{ return w == i; }
bool operator!=(uint64_t i) const
{ return w != i; }
bool operator==(const wtype& o) const
{ return w == o.w && w2 == o.w2; }
bool operator!=(const wtype& o) const
{ return w != o.w || w2 != o.w2; }
template <class Archive>
void serialize(Archive& ar, unsigned version)
{ ar & w; ar & w2; }
};
static
inline
std::ostream& operator<<(std::ostream& os, const wtype& w)
{
os << '(' << w.w << ',' << w.w2 << ')';
return os;
}
}
}
}
#endif

View File

@ -1,20 +1,80 @@
#ifndef _BOOST_HISTOGRAM_DETAIL_ZERO_SUPPRESSION_HPP_
#define _BOOST_HISTOGRAM_DETAIL_ZERO_SUPPRESSION_HPP_
#include <cstddef>
#include <boost/cstdint.hpp>
#include <boost/histogram/detail/wtype.hpp>
#include <limits>
#include <vector>
namespace boost {
namespace histogram {
namespace detail {
template <typename T>
bool
zero_suppression_encode(std::vector<char>& output, std::size_t output_max,
const char* input, std::size_t input_len);
zero_suppression_encode(std::vector<T>& output, const T* input,
uintptr_t size)
{
#define BOOST_HISTOGRAM_ZERO_SUPPRESSION_FILL { \
if ((size - output.size()) < 2) \
return false; \
output.push_back(0); \
output.push_back(nzero); \
nzero = 0; \
}
const T* input_end = input + size;
T nzero = 0;
for (; input != input_end; ++input) {
if (*input != 0) {
if (nzero)
BOOST_HISTOGRAM_ZERO_SUPPRESSION_FILL
if (output.size() == size)
return false;
output.push_back(*input);
}
else {
++nzero;
if (nzero == 0) // overflowed to zero
BOOST_HISTOGRAM_ZERO_SUPPRESSION_FILL
}
}
if (nzero)
BOOST_HISTOGRAM_ZERO_SUPPRESSION_FILL
return true;
}
template <typename T>
void
zero_suppression_decode(char* output, std::size_t output_len,
const std::vector<char>& input);
zero_suppression_decode(T* output, uintptr_t size,
const std::vector<T>& input)
{
const T* inp = &input[0];
const T* output_end = output + size;
while (output != output_end) {
*output = *inp;
if (*inp == 0) {
const uintptr_t nzero = *(++inp);
for (T j = 1; j != nzero; ++j) {
*(++output) = 0;
if (output == output_end)
return;
}
}
++inp;
++output;
}
}
template <>
void
zero_suppression_decode(wtype* output, uintptr_t size,
const std::vector<wtype>& input);
template <>
bool
zero_suppression_encode(std::vector<wtype>& output, const wtype* input,
uintptr_t size);
}
}

View File

@ -1,5 +1,5 @@
#ifndef _BOOST_HISTOGRAM_NHISTOGRAM_HPP_
#define _BOOST_HISTOGRAM_NHISTOGRAM_HPP_
#ifndef _BOOST_HISTOGRAM_HISTOGRAM_HPP_
#define _BOOST_HISTOGRAM_HISTOGRAM_HPP_
#include <boost/histogram/axis.hpp>
#include <boost/histogram/histogram_base.hpp>
@ -9,28 +9,27 @@
#include <boost/serialization/base_object.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/assert.hpp>
#include <boost/python/dict.hpp>
namespace boost {
namespace histogram {
class nhistogram : public histogram_base {
class histogram : public histogram_base {
public:
nhistogram() {}
histogram() {}
nhistogram(const nhistogram& o) :
histogram(const histogram& o) :
histogram_base(o),
data_(o.data_)
{}
explicit
nhistogram(const axes_type& axes) :
histogram(const axes_type& axes) :
histogram_base(axes),
data_(field_count())
{}
#define BOOST_NHISTOGRAM_CTOR(z, n, unused) \
nhistogram( BOOST_PP_ENUM_PARAMS_Z(z, n, const axis_type& a) ) : \
histogram( BOOST_PP_ENUM_PARAMS_Z(z, n, const axis_type& a) ) : \
histogram_base( BOOST_PP_ENUM_PARAMS_Z(z, n, a) ), \
data_(field_count()) \
{}
@ -73,12 +72,43 @@ BOOST_PP_REPEAT_FROM_TO(1, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_NHISTOGRAM_CTOR, ni
// generates fill functions taking 1 to AXIS_LIMT arguments
BOOST_PP_REPEAT_FROM_TO(1, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_NHISTOGRAM_FILL, nil)
template <typename Container>
inline
void wfill(const Container& v, double w)
{
BOOST_ASSERT(v.size() == dim());
const size_type k = pos(v);
if (k != uintmax_t(-1))
data_.increase(k, w);
}
// C-style call
inline
void wfill(unsigned n, const double* v, double w)
{
BOOST_ASSERT(n == dim());
const size_type k = pos(v);
if (k != uintmax_t(-1))
data_.increase(k, w);
}
#define BOOST_NHISTOGRAM_WFILL(z, n, unused) \
inline \
void wfill( BOOST_PP_ENUM_PARAMS_Z(z, n, double x), double w ) \
{ \
const double buffer[n] = { BOOST_PP_ENUM_PARAMS(n, x) }; \
wfill(n, buffer, w); /* size is checked here */ \
}
// generates wfill functions taking 1 to AXIS_LIMT arguments
BOOST_PP_REPEAT_FROM_TO(1, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_NHISTOGRAM_WFILL, nil)
template <typename Container>
double value(const Container& idx)
const
{
BOOST_ASSERT(idx.size() == dim());
return data_.read(linearize(idx));
return data_.value(linearize(idx));
}
// C-style call
@ -86,7 +116,7 @@ BOOST_PP_REPEAT_FROM_TO(1, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_NHISTOGRAM_FILL, ni
const
{
BOOST_ASSERT(n == dim());
return data_.read(linearize(idx));
return data_.value(linearize(idx));
}
#define BOOST_NHISTOGRAM_VALUE(z, n, unused) \
@ -100,11 +130,38 @@ BOOST_PP_REPEAT_FROM_TO(1, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_NHISTOGRAM_FILL, ni
// generates value functions taking 1 to AXIS_LIMT arguments
BOOST_PP_REPEAT_FROM_TO(1, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_NHISTOGRAM_VALUE, nil)
bool operator==(const nhistogram& o) const
template <typename Container>
double variance(const Container& idx)
const
{
BOOST_ASSERT(idx.size() == dim());
return data_.variance(linearize(idx));
}
// C-style call
double variance(unsigned n, const int* idx)
const
{
BOOST_ASSERT(n == dim());
return data_.variance(linearize(idx));
}
#define BOOST_NHISTOGRAM_VARIANCE(z, n, unused) \
double variance( BOOST_PP_ENUM_PARAMS_Z(z, n, int i) ) \
const \
{ \
const int idx[n] = { BOOST_PP_ENUM_PARAMS_Z(z, n, i) }; \
return variance(n, idx); /* size is checked here */ \
}
// generates variance functions taking 1 to AXIS_LIMT arguments
BOOST_PP_REPEAT_FROM_TO(1, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_NHISTOGRAM_VARIANCE, nil)
bool operator==(const histogram& o) const
{ return histogram_base::operator==(o) &&
data_ == o.data_; }
nhistogram& operator+=(const nhistogram& o)
histogram& operator+=(const histogram& o)
{ data_ += o.data_; return *this; }
private:
@ -118,11 +175,11 @@ private:
ar & data_;
}
friend python::dict nhistogram_array_interface(nhistogram&);
friend class buffer_access;
};
nhistogram operator+(const nhistogram& a, const nhistogram& b) {
nhistogram result(a);
histogram operator+(const histogram& a, const histogram& b) {
histogram result(a);
return result += b;
}

View File

@ -1,110 +0,0 @@
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include <boost/serialization/array.hpp>
class wstore {
public:
typedef boost::uintmax_t size_type;
struct wcount { double w_, w2_; };
private:
size_type size_;
double* buffer_;
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive & ar, unsigned version) {
using boost::serialization::make_array;
size_type s = size_;
ar & make_nvp("size", size_);
if (s != size_) {
destroy();
create();
}
ar & make_nvp("data", \
make_array(buffer_, size_ * 2));
}
void
create() {
buffer_ = (double*)std::calloc(size_, sizeof(wcount));
}
void
destroy() {
free(buffer_);
buffer_ = 0;
}
public:
wstore()
: size_(0), buffer_(0)
{}
wstore(size_type n)
: size_(n)
{
create();
}
wstore(const wstore& other)
: size_(other.size_)
{
create();
*this = other;
}
~wstore() { destroy(); }
wstore&
operator=(const wstore& other)
{
if (size_ != other.size_) {
destroy();
size_ = other.size_;
create();
}
std::memcpy(buffer_, other.buffer_, size_ * sizeof(wcount));
return *this;
}
inline
wcount&
operator[](size_type i)
{
return *((wcount*)buffer_ + i);
}
inline
const wcount&
operator[](size_type i) const
{
return *((wcount*)buffer_ + i);
}
wstore&
operator+=(const wstore& other) {
if (size_ != other.size_)
throw std::logic_error("sizes do not match");
for (size_type i = 0; i < (size_ * 2); ++i)
buffer_[i] += other.buffer_[i];
return *this;
}
bool
operator==(const wstore& other) const {
if (size_ != other.size_)
return false;
for (size_type i = 0; i < (size_ * 2); ++i)
if (buffer_[i] != other.buffer_[i])
return false;
return true;
}
inline size_type size() const { return size_; }
inline const double* buffer() const { return buffer_; }
};

View File

@ -1,16 +1,16 @@
#include <boost/histogram/nhistogram.hpp>
#include <boost/histogram/histogram.hpp>
#include <ostream>
namespace boost {
namespace histogram {
double
nhistogram::sum()
histogram::sum()
const
{
double result = 0.0;
for (size_type i = 0, n = field_count(); i < n; ++i)
result += data_.read(i);
result += data_.value(i);
return result;
}

View File

@ -50,8 +50,42 @@ nstore::operator+=(const nstore& o)
{
if (size_ != o.size_)
throw std::logic_error("sizes do not match");
if (depth_ != o.depth_) {
if (o.depth_ == sizeof(wtype))
wconvert();
else
while (depth_ < o.depth_)
grow();
}
if (depth_ == sizeof(wtype)) {
for (size_type i = 0; i < size_; ++i)
write(i, read(i) + o.read(i));
((wtype*)buffer_)[i] += ((wtype*)o.buffer_)[i];
}
else {
size_type i = 0;
while (i < size_) {
const uint64_t oi = o.ivalue(i);
switch (depth_) {
#define BOOST_HISTOGRAM_NSTORE_ADD(T) \
case sizeof(T): { \
T& b = ((T*)buffer_)[i]; \
if ((std::numeric_limits<T>::max() - b) >= oi) { \
b += oi; \
++i; \
break; \
} else grow(); /* add fall through */ \
}
BOOST_HISTOGRAM_NSTORE_ADD(uint8_t);
BOOST_HISTOGRAM_NSTORE_ADD(uint16_t);
BOOST_HISTOGRAM_NSTORE_ADD(uint32_t);
BOOST_HISTOGRAM_NSTORE_ADD(uint64_t);
#undef BOOST_HISTOGRAM_NSTORE_ADD
default: assert(!"invalid depth");
}
}
}
return *this;
}
@ -64,42 +98,31 @@ nstore::operator==(const nstore& o)
return std::memcmp(buffer_, o.buffer_, size_ * depth_) == 0;
}
uint64_t
nstore::read(size_type i)
double
nstore::value(size_type i)
const
{
if (depth_ == sizeof(wtype))
return ((wtype*)buffer_)[i].w;
return ivalue(i);
}
double
nstore::variance(size_type i)
const
{
switch (depth_) {
#define BOOST_HISTOGRAM_NSTORE_READ(T) \
case sizeof(wtype): return ((wtype*)buffer_)[i].w2;
#define BOOST_HISTOGRAM_NSTORE_VARIANCE(T) \
case sizeof(T): return ((T*)buffer_)[i]
BOOST_HISTOGRAM_NSTORE_READ(uint8_t);
BOOST_HISTOGRAM_NSTORE_READ(uint16_t);
BOOST_HISTOGRAM_NSTORE_READ(uint32_t);
BOOST_HISTOGRAM_NSTORE_READ(uint64_t);
#undef BOOST_HISTOGRAM_NSTORE_READ
default: assert(!"invalid depth");
}
return 0;
}
void
nstore::write(size_type i, uint64_t v)
{
const uint64_t vmax = max_count();
while (vmax < v) grow();
switch (depth_) {
#define BOOST_HISTOGRAM_NSTORE_WRITE(T) \
case sizeof(T): { \
((T*)buffer_)[i] = v; \
break; \
}
BOOST_HISTOGRAM_NSTORE_WRITE(uint8_t);
BOOST_HISTOGRAM_NSTORE_WRITE(uint16_t);
BOOST_HISTOGRAM_NSTORE_WRITE(uint32_t);
BOOST_HISTOGRAM_NSTORE_WRITE(uint64_t);
#undef BOOST_HISTOGRAM_NSTORE_WRITE
BOOST_HISTOGRAM_NSTORE_VARIANCE(uint8_t);
BOOST_HISTOGRAM_NSTORE_VARIANCE(uint16_t);
BOOST_HISTOGRAM_NSTORE_VARIANCE(uint32_t);
BOOST_HISTOGRAM_NSTORE_VARIANCE(uint64_t);
#undef BOOST_HISTOGRAM_NSTORE_VARIANCE
default: assert(!"invalid depth");
}
return 0.0;
}
void
@ -118,16 +141,16 @@ nstore::destroy()
void
nstore::grow()
{
if (depth_ == sizeof(uint64_t))
throw std::overflow_error("depth > 64 bit is not supported");
if (depth_ == 0 || buffer_ == 0)
throw std::logic_error("cannot call grow on null buffer");
assert(depth_ > 0);
assert(depth_ < sizeof(uint64_t));
assert(buffer_ != 0);
buffer_ = std::realloc(buffer_, size_ * 2 * depth_);
if (!buffer_) throw std::bad_alloc();
size_type i = size_;
switch (depth_) {
#define BOOST_HISTOGRAM_NSTORE_GROW(T0, T1) \
case sizeof(T0): \
for (size_type i = size_ - 1; i != size_type(-1); --i) \
while (i--) \
((T1*)buffer_)[i] = ((T0*)buffer_)[i]; \
break
BOOST_HISTOGRAM_NSTORE_GROW(uint8_t, uint16_t);
@ -138,17 +161,41 @@ nstore::grow()
depth_ *= 2;
}
void
nstore::wconvert()
{
assert(depth_ < sizeof(wtype));
buffer_ = std::realloc(buffer_, size_ * sizeof(wtype));
if (!buffer_) throw std::bad_alloc();
size_type i = size_;
switch (depth_) {
#define BOOST_HISTOGRAM_NSTORE_CONVERT(T) \
case sizeof(T): \
while (i--) \
((wtype*)buffer_)[i] = ((T*)buffer_)[i]; \
break
BOOST_HISTOGRAM_NSTORE_CONVERT(uint8_t);
BOOST_HISTOGRAM_NSTORE_CONVERT(uint16_t);
BOOST_HISTOGRAM_NSTORE_CONVERT(uint32_t);
BOOST_HISTOGRAM_NSTORE_CONVERT(uint64_t);
#undef BOOST_HISTOGRAM_NSTORE_CONVERT
default: break; // no nuthin'
}
depth_ = sizeof(wtype);
}
uint64_t
nstore::max_count()
nstore::ivalue(size_type i)
const
{
switch (depth_) {
#define BOOST_HISTOGRAM_NSTORE_CASE(T) \
case sizeof(T): return std::numeric_limits<T>::max()
BOOST_HISTOGRAM_NSTORE_CASE(uint8_t);
BOOST_HISTOGRAM_NSTORE_CASE(uint16_t);
BOOST_HISTOGRAM_NSTORE_CASE(uint32_t);
BOOST_HISTOGRAM_NSTORE_CASE(uint64_t);
#define BOOST_HISTOGRAM_NSTORE_IVALUE(T) \
case sizeof(T): return ((T*)buffer_)[i]
BOOST_HISTOGRAM_NSTORE_IVALUE(uint8_t);
BOOST_HISTOGRAM_NSTORE_IVALUE(uint16_t);
BOOST_HISTOGRAM_NSTORE_IVALUE(uint32_t);
BOOST_HISTOGRAM_NSTORE_IVALUE(uint64_t);
#undef BOOST_HISTOGRAM_NSTORE_IVALUE
default: assert(!"invalid depth");
}
return 0;

View File

@ -1,10 +1,10 @@
#include "serialization_suite.hpp"
#include <boost/histogram/axis.hpp>
#include <boost/histogram/nhistogram.hpp>
#include <boost/histogram/histogram.hpp>
#include <boost/python.hpp>
#include <boost/python/raw_function.hpp>
#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
#include "serialization_suite.hpp"
#ifdef USE_NUMPY
# define NO_IMPORT_ARRAY
# define PY_ARRAY_UNIQUE_SYMBOL boost_histogram_ARRAY_API
@ -16,7 +16,7 @@ namespace boost {
namespace histogram {
python::object
nhistogram_init(python::tuple args, python::dict kwargs) {
histogram_init(python::tuple args, python::dict kwargs) {
using namespace python;
using python::tuple;
@ -48,24 +48,12 @@ nhistogram_init(python::tuple args, python::dict kwargs) {
return pyinit(axes);
}
python::dict
nhistogram_array_interface(nhistogram& self) {
python::list shape;
for (unsigned i = 0; i < self.dim(); ++i)
shape.append(self.shape(i));
python::dict d;
d["shape"] = python::tuple(shape);
d["typestr"] = python::str("<u") + python::str(self.depth());
d["data"] = python::make_tuple((long long)(self.data_.buffer()), false);
return d;
}
python::object
nhistogram_fill(python::tuple args, python::dict kwargs) {
histogram_fill(python::tuple args, python::dict kwargs) {
using namespace python;
const unsigned nargs = len(args);
nhistogram& self = extract<nhistogram&>(args[0]);
histogram& self = extract<histogram&>(args[0]);
#ifdef USE_NUMPY
if (nargs == 2) {
@ -128,7 +116,7 @@ nhistogram_fill(python::tuple args, python::dict kwargs) {
}
uint64_t
nhistogram_getitem(const nhistogram& self, python::object oidx) {
histogram_getitem(const histogram& self, python::object oidx) {
using namespace python;
if (self.dim() == 1)
@ -147,26 +135,42 @@ nhistogram_getitem(const nhistogram& self, python::object oidx) {
return self.value(self.dim(), idx);
}
void register_nhistogram()
class buffer_access {
public:
static
python::dict
histogram_array_interface(histogram& self) {
python::list shape;
for (unsigned i = 0; i < self.dim(); ++i)
shape.append(self.shape(i));
python::dict d;
d["shape"] = python::tuple(shape);
d["typestr"] = python::str("<u") + python::str(self.data_.depth());
d["data"] = python::make_tuple((long long)(self.data_.buffer()), false);
return d;
}
};
void register_histogram()
{
using namespace python;
class_<
nhistogram, bases<histogram_base>,
shared_ptr<nhistogram>
>("nhistogram", no_init)
.def("__init__", raw_function(nhistogram_init))
histogram, bases<histogram_base>,
shared_ptr<histogram>
>("histogram", no_init)
.def("__init__", raw_function(histogram_init))
// shadowed C++ ctors
.def(init<const axes_type&>())
.add_property("__array_interface__", nhistogram_array_interface)
.def("fill", raw_function(nhistogram_fill))
.add_property("depth", &nhistogram::depth)
.add_property("sum", &nhistogram::sum)
.def("__getitem__", nhistogram_getitem)
.add_property("__array_interface__", &buffer_access::histogram_array_interface)
.def("fill", raw_function(histogram_fill))
.add_property("depth", &histogram::depth)
.add_property("sum", &histogram::sum)
.def("__getitem__", histogram_getitem)
.def(self == self)
.def(self += self)
.def(self + self)
.def_pickle(serialization_suite<nhistogram>())
.def_pickle(serialization_suite<histogram>())
;
}

View File

@ -8,7 +8,7 @@
namespace boost {
namespace histogram {
void register_histogram_base();
void register_nhistogram();
void register_histogram();
}
}
@ -18,5 +18,5 @@ BOOST_PYTHON_MODULE(histogram)
import_array();
#endif
boost::histogram::register_histogram_base();
boost::histogram::register_nhistogram();
boost::histogram::register_histogram();
}

View File

@ -4,50 +4,52 @@ namespace boost {
namespace histogram {
namespace detail {
template <>
bool
zero_suppression_encode(std::vector<char>& output, std::size_t output_max,
const char* input, std::size_t input_len)
zero_suppression_encode(std::vector<wtype>& output, const wtype* input,
uintptr_t size)
{
#define FILL_OUTPUT { \
if ((output_max - output.size()) < 2) \
#define BOOST_HISTOGRAM_ZERO_SUPPRESSION_FILL { \
if ((size - output.size()) < 2) \
return false; \
output.push_back(0); \
output.push_back(nzero); \
nzero = 0; \
}
const char* input_end = input + input_len;
unsigned nzero = 0;
const wtype* input_end = input + size;
uint32_t nzero = 0;
for (; input != input_end; ++input) {
if (*input != 0) {
if (nzero)
FILL_OUTPUT
if (output.size() == output_max)
BOOST_HISTOGRAM_ZERO_SUPPRESSION_FILL
if (output.size() == size)
return false;
output.push_back(*input);
}
else {
++nzero;
if (nzero == 256)
FILL_OUTPUT
if (nzero == 0) // overflowed to zero
BOOST_HISTOGRAM_ZERO_SUPPRESSION_FILL
}
}
if (nzero)
FILL_OUTPUT
BOOST_HISTOGRAM_ZERO_SUPPRESSION_FILL
return true;
}
template <>
void
zero_suppression_decode(char* output, std::size_t output_len,
const std::vector<char>& input)
zero_suppression_decode(wtype* output, uintptr_t size,
const std::vector<wtype>& input)
{
const char* inp = &input[0];
const char* output_end = output + output_len;
const wtype* inp = &input[0];
const wtype* output_end = output + size;
while (output != output_end) {
*output = *inp;
if (*inp == 0) {
const char nzero = *(++inp);
for (char j = 1; j != nzero; ++j) {
const uintptr_t nzero = (++inp)->w;
for (uintptr_t j = 1; j != nzero; ++j) {
*(++output) = 0;
if (output == output_end)
return;

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
import unittest
from math import pi
from histogram import nhistogram, regular_axis, polar_axis, \
from histogram import histogram, regular_axis, polar_axis, \
variable_axis, category_axis, integer_axis
import cPickle
import StringIO
@ -299,39 +299,39 @@ class test_integer_axis(unittest.TestCase):
self.assertEqual(a.index(3), 4)
self.assertEqual(a.index(4), 4)
class nhistogram_test(unittest.TestCase):
class histogram_test(unittest.TestCase):
def test_init(self):
nhistogram(integer_axis(-1, 1))
histogram(integer_axis(-1, 1))
with self.assertRaises(TypeError):
nhistogram(1)
histogram(1)
with self.assertRaises(TypeError):
nhistogram("bla")
histogram("bla")
with self.assertRaises(TypeError):
nhistogram([])
histogram([])
with self.assertRaises(TypeError):
nhistogram(regular_axis)
histogram(regular_axis)
with self.assertRaises(TypeError):
nhistogram(regular_axis())
histogram(regular_axis())
with self.assertRaises(TypeError):
nhistogram([integer_axis(-1, 1)])
histogram([integer_axis(-1, 1)])
with self.assertRaises(TypeError):
nhistogram(integer_axis(-1, 1), unknown_keyword="nh")
histogram(integer_axis(-1, 1), unknown_keyword="nh")
h = nhistogram(integer_axis(-1, 1))
h = histogram(integer_axis(-1, 1))
self.assertEqual(h.dim, 1)
self.assertEqual(h.axis(0), integer_axis(-1, 1))
self.assertEqual(h.shape(0), 5)
self.assertEqual(h.depth, 1)
self.assertEqual(nhistogram(integer_axis(-1, 1, uoflow=False)).shape(0), 3)
self.assertNotEqual(h, nhistogram(regular_axis(1, -1, 1)))
self.assertNotEqual(h, nhistogram(integer_axis(-1, 2)))
self.assertNotEqual(h, nhistogram(integer_axis(-1, 1, label="ia")))
self.assertNotEqual(h, nhistogram(integer_axis(-1, 1, uoflow=True)))
self.assertEqual(histogram(integer_axis(-1, 1, uoflow=False)).shape(0), 3)
self.assertNotEqual(h, histogram(regular_axis(1, -1, 1)))
self.assertNotEqual(h, histogram(integer_axis(-1, 2)))
self.assertNotEqual(h, histogram(integer_axis(-1, 1, label="ia")))
self.assertNotEqual(h, histogram(integer_axis(-1, 1, uoflow=True)))
def test_fill_1d(self):
h0 = nhistogram(integer_axis(-1, 1, uoflow=False))
h1 = nhistogram(integer_axis(-1, 1, uoflow=True))
h0 = histogram(integer_axis(-1, 1, uoflow=False))
h1 = histogram(integer_axis(-1, 1, uoflow=True))
for h in (h0, h1):
with self.assertRaises(StandardError):
h.fill()
@ -363,7 +363,7 @@ class nhistogram_test(unittest.TestCase):
self.assertEqual(h1[3], 1)
def test_growth(self):
h = nhistogram(integer_axis(-1, 1))
h = histogram(integer_axis(-1, 1))
h.fill(-1)
h.fill(1)
h.fill(1)
@ -382,7 +382,7 @@ class nhistogram_test(unittest.TestCase):
def test_fill_2d(self):
for uoflow in (False, True):
h = nhistogram(integer_axis(-1, 1, uoflow=uoflow),
h = histogram(integer_axis(-1, 1, uoflow=uoflow),
regular_axis(4, -2, 2, uoflow=uoflow))
h.fill(-1, -2)
h.fill(-1, -1)
@ -407,7 +407,7 @@ class nhistogram_test(unittest.TestCase):
def test_add_2d(self):
for uoflow in (False, True):
h = nhistogram(integer_axis(-1, 1, uoflow=uoflow),
h = histogram(integer_axis(-1, 1, uoflow=uoflow),
regular_axis(4, -2, 2, uoflow=uoflow))
h.fill(-1, -2)
h.fill(-1, -1)
@ -432,7 +432,7 @@ class nhistogram_test(unittest.TestCase):
self.assertEqual(h[i, j], 2 * m[i][j])
def test_pickle(self):
a = nhistogram(category_axis('A', 'B', 'C'),
a = histogram(category_axis('A', 'B', 'C'),
integer_axis(0, 3, label='ia'),
regular_axis(4, 0.0, 4.0, uoflow=False),
variable_axis(0.0, 1.0, 2.0))
@ -460,7 +460,7 @@ class nhistogram_test(unittest.TestCase):
@unittest.skipUnless("numpy" in globals(), "requires numpy")
def test_numpy_conversion(self):
a = nhistogram(integer_axis(0, 2, uoflow=False))
a = histogram(integer_axis(0, 2, uoflow=False))
for i in xrange(100):
a.fill(1)
b = numpy.array(a) # a copy
@ -481,19 +481,19 @@ class nhistogram_test(unittest.TestCase):
@unittest.skipUnless("numpy" in globals(), "requires numpy")
def test_fill_with_numpy_array(self):
a = nhistogram(integer_axis(0, 2, uoflow=False))
a = histogram(integer_axis(0, 2, uoflow=False))
a.fill(numpy.array([-1, 0, 1, 2, 1, 4]))
self.assertEqual(a[0], 1)
self.assertEqual(a[1], 2)
self.assertEqual(a[2], 1)
a = nhistogram(integer_axis(0, 1, uoflow=False),
a = histogram(integer_axis(0, 1, uoflow=False),
regular_axis(2, 0, 2, uoflow=False))
a.fill(numpy.array([[-1., -1.], [0., 1.], [1., 0.1]]))
self.assertEqual(a[0, 0], 0)
self.assertEqual(a[0, 1], 1)
self.assertEqual(a[1, 0], 1)
self.assertEqual(a[1, 1], 0)
a = nhistogram(integer_axis(0, 2, uoflow=False))
a = histogram(integer_axis(0, 2, uoflow=False))
a.fill([0, 0, 1, 2])
a.fill((1, 0, 2, 2))
self.assertEqual(a[0], 3)

View File

@ -5,150 +5,278 @@
#include <boost/assign/std/vector.hpp>
#include <iostream>
using namespace boost::assign;
using boost::histogram::detail::zero_suppression_encode;
using boost::histogram::detail::zero_suppression_decode;
using namespace boost::histogram::detail;
namespace tt = boost::test_tools;
template <typename T>
void
print(const std::vector<char>& v) {
print(const std::vector<T>& v) {
std::cerr << "[";
for (unsigned i = 0; i < v.size(); ++i) {
std::cerr << unsigned(v[i]) << (i < v.size() - 1 ? ", " : "]");
std::cerr << v[i] << (i < v.size() - 1 ? ", " : "]");
}
std::cerr << "\n";
}
#define EQUAL_VECTORS(a, b) \
BOOST_CHECK_EQUAL_COLLECTIONS(a.begin(), a.end(), b.begin(), b.end())
#define EQUAL_VECTORS(a, b) BOOST_CHECK_EQUAL_COLLECTIONS(a.begin(), a.end(), b.begin(), b.end())
BOOST_AUTO_TEST_CASE( codec_no_zero )
{
std::vector<char> a, b, c(3, 0);
std::vector<unsigned> a, b, c(3, 0);
a += 1, 1, 1;
BOOST_CHECK(zero_suppression_encode(b, 3, &a[0], a.size()));
BOOST_CHECK(zero_suppression_encode<unsigned>(b, &a[0], a.size()));
EQUAL_VECTORS(a, b);
zero_suppression_decode(&c[0], c.size(), b);
zero_suppression_decode<unsigned>(&c[0], c.size(), b);
EQUAL_VECTORS(a, c);
}
BOOST_AUTO_TEST_CASE( codec_fail )
{
std::vector<char> a, b;
a += 1, 1, 1;
BOOST_CHECK(zero_suppression_encode(b, 2, &a[0], a.size()) == false);
}
BOOST_AUTO_TEST_CASE( codec_empty )
{
std::vector<char> a, b, c;
BOOST_CHECK(zero_suppression_encode(b, 3, &a[0], a.size()));
std::vector<unsigned> a, b, c;
BOOST_CHECK(zero_suppression_encode<unsigned>(b, &a[0], a.size()));
EQUAL_VECTORS(a, b);
zero_suppression_decode(&c[0], c.size(), b);
zero_suppression_decode<unsigned>(&c[0], c.size(), b);
EQUAL_VECTORS(a, c);
}
BOOST_AUTO_TEST_CASE( codec_zero_0 )
BOOST_AUTO_TEST_CASE( codec_zero_0a )
{
std::vector<char> a, b, c, d(2, 0);
a += 0, 1;
c += 0, 1, 1;
BOOST_CHECK(zero_suppression_encode(b, c.size(), &a[0], a.size()));
std::vector<uint8_t> a, b;
a += 0;
BOOST_CHECK(zero_suppression_encode<uint8_t>(b, &a[0], a.size()) == false);
}
BOOST_AUTO_TEST_CASE( codec_zero_1a )
{
std::vector<uint8_t> a, b, c, d(3, 0);
a += 1, 0, 0;
c += 1, 0, 2;
BOOST_CHECK(zero_suppression_encode<uint8_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode(&d[0], d.size(), b);
zero_suppression_decode<uint8_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_1 )
BOOST_AUTO_TEST_CASE( codec_zero_2a )
{
std::vector<char> a, b, c, d(3, 0);
std::vector<uint8_t> a, b, c, d(3, 0);
a += 0, 0, 1;
c += 0, 2, 1;
BOOST_CHECK(zero_suppression_encode(b, c.size(), &a[0], a.size()));
BOOST_CHECK(zero_suppression_encode<uint8_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode(&d[0], d.size(), b);
zero_suppression_decode<uint8_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_2 )
BOOST_AUTO_TEST_CASE( codec_zero_3a )
{
std::vector<char> a, b, c, d(2, 0);
std::vector<uint8_t> a, b, c, d(2, 0);
a += 0, 0;
c += 0, 2;
BOOST_CHECK(zero_suppression_encode(b, c.size(), &a[0], a.size()));
BOOST_CHECK(zero_suppression_encode<uint8_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode(&d[0], d.size(), b);
zero_suppression_decode<uint8_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_3 )
BOOST_AUTO_TEST_CASE( codec_zero_0b )
{
std::vector<char> a, b, c, d(1, 0);
std::vector<unsigned> a, b;
a += 0;
c += 0, 1;
BOOST_CHECK(zero_suppression_encode(b, c.size(), &a[0], a.size()));
BOOST_CHECK(zero_suppression_encode<unsigned>(b, &a[0], a.size()) == false);
}
BOOST_AUTO_TEST_CASE( codec_zero_1b )
{
std::vector<unsigned> a, b, c, d(3, 0);
a += 1, 0, 0;
c += 1, 0, 2;
BOOST_CHECK(zero_suppression_encode<unsigned>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode(&d[0], d.size(), b);
zero_suppression_decode<unsigned>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_2b )
{
std::vector<unsigned> a, b, c, d(3, 0);
a += 0, 0, 1;
c += 0, 2, 1;
BOOST_CHECK(zero_suppression_encode<unsigned>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode<unsigned>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_3b )
{
std::vector<unsigned> a, b, c, d(2, 0);
a += 0, 0;
c += 0, 2;
BOOST_CHECK(zero_suppression_encode<unsigned>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode<unsigned>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_0c )
{
std::vector<uint64_t> a, b;
a += 0;
BOOST_CHECK(zero_suppression_encode<uint64_t>(b, &a[0], a.size()) == false);
}
BOOST_AUTO_TEST_CASE( codec_zero_1c )
{
std::vector<uint64_t> a, b, c, d(3, 0);
a += 1, 0, 0;
c += 1, 0, 2;
BOOST_CHECK(zero_suppression_encode<uint64_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode<uint64_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_2c )
{
std::vector<uint64_t> a, b, c, d(3, 0);
a += 0, 0, 1;
c += 0, 2, 1;
BOOST_CHECK(zero_suppression_encode<uint64_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode<uint64_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_3c )
{
std::vector<uint64_t> a, b, c, d(2, 0);
a += 0, 0;
c += 0, 2;
BOOST_CHECK(zero_suppression_encode<uint64_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode<uint64_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_0d )
{
std::vector<wtype> a, b;
a += 0;
BOOST_CHECK(zero_suppression_encode<wtype>(b, &a[0], a.size()) == false);
}
BOOST_AUTO_TEST_CASE( codec_zero_1d )
{
std::vector<wtype> a, b, c, d(3, 0);
a += 1, 0, 0;
c += 1, 0, 2;
BOOST_CHECK(zero_suppression_encode<wtype>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode<wtype>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_2d )
{
std::vector<wtype> a, b, c, d(3, 0);
a += 0, 0, 1;
c += 0, 2, 1;
BOOST_CHECK(zero_suppression_encode<wtype>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode<wtype>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_3d )
{
std::vector<wtype> a, b, c, d(2, 0);
a += 0, 0;
c += 0, 2;
BOOST_CHECK(zero_suppression_encode<wtype>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode<wtype>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_4 )
{
std::vector<char> a, b, c, d(3, 0);
a += 0, 1, 0;
c += 0, 1, 1, 0, 1;
BOOST_CHECK(zero_suppression_encode(b, c.size(), &a[0], a.size()));
std::vector<unsigned> a, b, c, d(5, 0);
a += 0, 0, 0, 1, 0;
c += 0, 3, 1, 0, 1;
BOOST_CHECK(zero_suppression_encode<unsigned>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode(&d[0], d.size(), b);
zero_suppression_decode<unsigned>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_5 )
{
std::vector<char> a, b, c, d(4, 0);
a += 0, 1, 0, 0;
c += 0, 1, 1, 0, 2;
BOOST_CHECK(zero_suppression_encode(b, c.size(), &a[0], a.size()));
std::vector<unsigned> a, b, c, d(5, 0);
a += 0, 1, 0, 0, 0;
c += 0, 1, 1, 0, 3;
BOOST_CHECK(zero_suppression_encode<unsigned>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode(&d[0], d.size(), b);
zero_suppression_decode<unsigned>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_6 )
{
std::vector<char> a(255, 0), b, c, d(255, 0);
std::vector<uint8_t> a(255, 0), b, c, d(255, 0);
c += 0, 255;
BOOST_CHECK(zero_suppression_encode(b, c.size(), &a[0], a.size()));
BOOST_CHECK(zero_suppression_encode<uint8_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode(&d[0], d.size(), b);
zero_suppression_decode<uint8_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_7 )
{
std::vector<char> a(256, 0), b, c, d(256, 0);
std::vector<uint8_t> a(256, 0), b, c, d(256, 0);
c += 0, 0;
BOOST_CHECK(zero_suppression_encode(b, c.size(), &a[0], a.size()));
BOOST_CHECK(zero_suppression_encode<uint8_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode(&d[0], d.size(), b);
zero_suppression_decode<uint8_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_8 )
{
std::vector<char> a(257, 0), b, c, d(257, 0);
std::vector<uint8_t> a(257, 0), b, c, d(257, 0);
c += 0, 0, 0, 1;
BOOST_CHECK(zero_suppression_encode(b, c.size(), &a[0], a.size()));
BOOST_CHECK(zero_suppression_encode<uint8_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode(&d[0], d.size(), b);
zero_suppression_decode<uint8_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_9 )
{
std::vector<char> a(1000, 0), b, c, d(1000, 0);
std::vector<uint8_t> a(1000, 0), b, c, d(1000, 0);
c += 0, 0, 0, 0, 0, 0, 0, 232;
BOOST_CHECK(zero_suppression_encode(b, c.size(), &a[0], a.size()));
BOOST_CHECK(zero_suppression_encode<uint8_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode(&d[0], d.size(), b);
zero_suppression_decode<uint8_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_10 )
{
std::vector<uint16_t> a(1000, 0), b, c, d(1000, 0);
c += 0, 1000;
BOOST_CHECK(zero_suppression_encode<uint16_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode<uint16_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}
BOOST_AUTO_TEST_CASE( codec_zero_11 )
{
std::vector<uint16_t> a(65536, 0), b, c, d(65536, 0);
c += 0, 0;
BOOST_CHECK(zero_suppression_encode<uint16_t>(b, &a[0], a.size()));
EQUAL_VECTORS(b, c);
zero_suppression_decode<uint16_t>(&d[0], d.size(), b);
EQUAL_VECTORS(a, d);
}