asserts on dimension of input

This commit is contained in:
Hans Dembinski 2016-04-07 21:04:07 -04:00
parent 8e792c60dc
commit c4cf612a13
5 changed files with 79 additions and 51 deletions

View File

@ -1,6 +1,7 @@
#include <boost/histogram/nhistogram.hpp>
#include <boost/histogram/axis.hpp>
#include <boost/random.hpp>
#include <boost/array.hpp>
#include <TH1I.h>
#include <TH3I.h>
@ -50,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, std::string(), true));
nhistogram h(regular_axis(100, 0, 1));
t = clock();
for (unsigned i = 0; i < n; ++i)
h.fill(r[i]);
@ -79,9 +80,9 @@ 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, "", true),
regular_axis(100, 0, 1, "", true),
regular_axis(100, 0, 1, "", true));
nhistogram h(regular_axis(100, 0, 1),
regular_axis(100, 0, 1),
regular_axis(100, 0, 1));
t = clock();
for (unsigned i = 0; i < n; ++i)
h.fill(r[3 * i], r[3 * i + 1], r[3 * i + 2]);
@ -123,12 +124,13 @@ void compare_6d(unsigned n)
regular_axis(10, 0, 1),
regular_axis(10, 0, 1),
regular_axis(10, 0, 1));
boost::array<double, 6> y;
t = clock();
for (unsigned i = 0; i < n; ++i) {
for (unsigned k = 0; k < 6; ++k)
x[k] = r[6 * i + k];
h.fill(x);
y[k] = r[6 * i + k];
h.fill(y);
}
t = clock() - t;
best_boost = std::min(best_boost, double(t) / CLOCKS_PER_SEC);
@ -141,6 +143,6 @@ void compare_6d(unsigned n)
int main(int argc, char** argv) {
compare_1d(1000000);
compare_3d(100000);
compare_3d(500000);
compare_6d(100000);
}

View File

@ -15,6 +15,7 @@
namespace boost {
namespace histogram {
// common base class for most axes
class axis_base {
public:
inline unsigned bins() const { return size_ > 0 ? size_ : -size_; }
@ -26,7 +27,7 @@ protected:
axis_base(int, const std::string&, bool);
axis_base() : size_(0) {}
explicit axis_base(const axis_base&);
axis_base(const axis_base&);
axis_base& operator=(const axis_base&);
bool operator==(const axis_base&) const;
@ -45,6 +46,7 @@ private:
}
};
// mixin for real-valued axes
template <typename Derived>
class real_axis {
public:
@ -71,7 +73,7 @@ public:
bool uoflow = true);
regular_axis() {}
explicit regular_axis(const regular_axis&);
regular_axis(const regular_axis&);
regular_axis& operator=(const regular_axis&);
inline int index(double x) const {
@ -98,11 +100,12 @@ private:
// real polar axis (constant bin widths, wraps around)
class polar_axis: public axis_base, public real_axis<polar_axis> {
public:
explicit
polar_axis(unsigned n, double start = 0.0,
const std::string& label = std::string());
polar_axis() {}
explicit polar_axis(const polar_axis&);
polar_axis(const polar_axis&);
polar_axis& operator=(const polar_axis&);
inline int index(double x) const {
@ -130,6 +133,7 @@ private:
class variable_axis : public axis_base, public real_axis<variable_axis> {
public:
template <typename Container>
explicit
variable_axis(const Container& x,
const std::string& label = std::string(),
bool uoflow = true) :
@ -152,7 +156,7 @@ public:
}
variable_axis() {}
explicit variable_axis(const variable_axis&);
variable_axis(const variable_axis&);
variable_axis& operator=(const variable_axis&);
inline int index(double x) const {
@ -180,11 +184,13 @@ class category_axis {
public:
typedef std::string value_type;
explicit
category_axis(const std::string&);
explicit
category_axis(const std::vector<std::string>&);
category_axis() {}
explicit category_axis(const category_axis&);
category_axis(const category_axis&);
category_axis& operator=(const category_axis&);
inline unsigned bins() const { return categories_.size(); }
@ -213,7 +219,7 @@ public:
bool uoflow = true);
integer_axis() {}
explicit integer_axis(const integer_axis&);
integer_axis(const integer_axis&);
integer_axis& operator=(const integer_axis&);
inline int index(double x) const

View File

@ -44,11 +44,8 @@ public:
protected:
histogram_base() {}
explicit histogram_base(const axes_type& axes);
explicit histogram_base(const axis_type& a) : axes_(1, a) { update_buffers(); }
#define BOOST_HISTOGRAM_BASE_APPEND(z, n, unused) axes_.push_back(a ## n);
#define BOOST_HISTOGRAM_BASE_CTOR(z, n, unused) \
histogram_base( BOOST_PP_ENUM_PARAMS_Z(z, n, const axis_type& a) ) \
@ -59,7 +56,7 @@ protected:
}
// generates constructors taking 2 to AXIS_LIMIT arguments
BOOST_PP_REPEAT_FROM_TO(2, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_HISTOGRAM_BASE_CTOR, nil)
BOOST_PP_REPEAT_FROM_TO(1, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_HISTOGRAM_BASE_CTOR, nil)
bool operator==(const histogram_base&) const;
bool operator!=(const histogram_base& o) const
@ -68,7 +65,7 @@ BOOST_PP_REPEAT_FROM_TO(2, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_HISTOGRAM_BASE_CTOR
template <typename Array>
inline
size_type pos(const Array& v) const {
int32_t idx[BOOST_HISTOGRAM_AXIS_LIMIT];
int idx[BOOST_HISTOGRAM_AXIS_LIMIT];
for (unsigned i = 0, n = axes_.size(); i < n; ++i)
idx[i] = apply_visitor(detail::index_visitor(v[i]), axes_[i]);
return linearize(idx);

View File

@ -8,6 +8,8 @@
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/assert.hpp>
#include <boost/concept/requires.hpp>
#include <ostream>
#include <vector>
@ -18,15 +20,14 @@ class nhistogram : public histogram_base {
public:
nhistogram() {}
explicit
nhistogram(const axes_type& axes) :
histogram_base(axes),
data_(field_count())
nhistogram(const nhistogram& o) :
histogram_base(o),
data_(o.data_)
{}
explicit
nhistogram(const axis_type& a) :
histogram_base(a),
nhistogram(const axes_type& axes) :
histogram_base(axes),
data_(field_count())
{}
@ -36,47 +37,69 @@ public:
data_(field_count()) \
{}
// generates constructors taking 2 to AXIS_LIMIT arguments
BOOST_PP_REPEAT_FROM_TO(2, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_NHISTOGRAM_CTOR, nil)
// generates constructors taking 1 to AXIS_LIMIT arguments
BOOST_PP_REPEAT_FROM_TO(1, BOOST_HISTOGRAM_AXIS_LIMIT, BOOST_NHISTOGRAM_CTOR, nil)
double sum() const;
template <typename Array>
template <typename T>
inline
void fill(const Array& v)
void fill(const T& v)
{
BOOST_ASSERT(v.size() == dim());
const size_type k = pos(v);
if (k != uintmax_t(-1))
data_.increase(k);
}
void fill(double x,
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PP_DEC(BOOST_HISTOGRAM_AXIS_LIMIT),
double x, 0.0))
// C-style call
inline
void fill(unsigned n, const double* v)
{
const double buffer[BOOST_HISTOGRAM_AXIS_LIMIT] = {
x, BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_HISTOGRAM_AXIS_LIMIT), x)
};
fill(buffer);
BOOST_ASSERT(n == dim());
const size_type k = pos(v);
if (k != uintmax_t(-1))
data_.increase(k);
}
#define BOOST_NHISTOGRAM_FILL(z, n, unused) \
inline \
void fill( BOOST_PP_ENUM_PARAMS_Z(z, n, double x) ) \
{ \
const double buffer[n] = { BOOST_PP_ENUM_PARAMS(n, x) }; \
fill(n, buffer); /* size is checked here */ \
}
// 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 Array>
inline
size_type operator()(const Array& idx)
const
{ return data_.read(linearize(idx)); }
size_type operator()(int i,
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PP_DEC(BOOST_HISTOGRAM_AXIS_LIMIT),
int i, 0))
double value(const Array& idx)
const
{
const int32_t idx[BOOST_HISTOGRAM_AXIS_LIMIT] = {
i, BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_HISTOGRAM_AXIS_LIMIT), i)
};
return operator()(idx);
BOOST_ASSERT(idx.size() == dim());
return data_.read(linearize(idx));
}
// C-style call
double value(unsigned n, const int* idx)
const
{
BOOST_ASSERT(n == dim());
return data_.read(linearize(idx));
}
#define BOOST_NHISTOGRAM_VALUE(z, n, unused) \
double value( BOOST_PP_ENUM_PARAMS_Z(z, n, int i) ) \
const \
{ \
const int idx[n] = { BOOST_PP_ENUM_PARAMS_Z(z, n, i) }; \
return value(n, idx); /* size is checked here */ \
}
// 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
{ return histogram_base::operator==(o) &&
data_ == o.data_; }

View File

@ -104,7 +104,7 @@ nhistogram_fill(python::tuple args, python::dict kwargs) {
for (unsigned i = 0; i < dims[0]; ++i) {
double* v = (double*)PyArray_GETPTR1(a, i);
self.fill(v);
self.fill(self.dim(), v);
}
Py_DECREF(a);
@ -127,7 +127,7 @@ nhistogram_fill(python::tuple args, python::dict kwargs) {
double v[BOOST_HISTOGRAM_AXIS_LIMIT];
for (unsigned i = 0; i < dim; ++i)
v[i] = extract<double>(args[1 + i]);
self.fill(v);
self.fill(self.dim(), v);
return object();
}
@ -141,7 +141,7 @@ nhistogram_getitem(const nhistogram& self, python::object oidx) {
using namespace python;
if (self.dim() == 1)
return self(extract<int>(oidx)());
return self.value(extract<int>(oidx)());
const unsigned dim = len(oidx);
if (dim != self.dim()) {
@ -153,7 +153,7 @@ nhistogram_getitem(const nhistogram& self, python::object oidx) {
for (unsigned i = 0; i < dim; ++i)
idx[i] = extract<int>(oidx[i]);
return self(idx);
return self.value(self.dim(), idx);
}
void register_nhistogram()