mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-09 23:04:07 +00:00
new feature, filling with weights
This commit is contained in:
parent
14c7a282dc
commit
103fa6cf0a
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
47
include/boost/histogram/detail/wtype.hpp
Normal file
47
include/boost/histogram/detail/wtype.hpp
Normal 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
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_; }
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
133
src/nstore.cpp
133
src/nstore.cpp
@ -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;
|
||||
|
@ -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>())
|
||||
;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user