From 14c43544bc56a0c2e220f8694d3f727af2057d3b Mon Sep 17 00:00:00 2001 From: Hans Dembinski Date: Sat, 4 Nov 2017 00:15:50 +0100 Subject: [PATCH] added pow transform, transforms can now be used from python --- include/boost/histogram/axis.hpp | 177 +++++++++--------- .../histogram/axis_ostream_operators.hpp | 41 +++- .../boost/histogram/detail/axis_visitor.hpp | 22 +-- include/boost/histogram/interval.hpp | 41 ++-- include/boost/histogram/serialization.hpp | 11 +- include/boost/histogram/utility.hpp | 6 +- src/python/axis.cpp | 124 ++++++++---- test/axis_test.cpp | 44 ++--- test/histogram_test.cpp | 2 +- 9 files changed, 266 insertions(+), 202 deletions(-) diff --git a/include/boost/histogram/axis.hpp b/include/boost/histogram/axis.hpp index 625d258e..eac213b6 100644 --- a/include/boost/histogram/axis.hpp +++ b/include/boost/histogram/axis.hpp @@ -7,13 +7,13 @@ #ifndef _BOOST_HISTOGRAM_AXIS_HPP_ #define _BOOST_HISTOGRAM_AXIS_HPP_ -#include #include +#include +#include #include #include #include #include -#include #include #include #include @@ -21,9 +21,9 @@ #include #include #include -#include -#include #include +#include +#include // forward declaration for serialization namespace boost { @@ -40,39 +40,35 @@ namespace axis { enum { with_uoflow = true, without_uoflow = false }; namespace detail { - // similar to boost::reference_wrapper, but with default ctor - template - class cref { - public: - cref() = default; - cref(const T& t) : ptr_(&t) {} - operator const T&() const { return *ptr_; } - private: - const T* ptr_ = nullptr; - }; +// similar to boost::reference_wrapper, but with default ctor +template class cref { +public: + cref() = default; + cref(const T &t) : ptr_(&t) {} + operator const T &() const { return *ptr_; } - template - using axis_iterator_value = - std::pair::value, - cref< - typename remove_reference::type - >, - typename Axis::bin_type - >::type - >; -} +private: + const T *ptr_ = nullptr; +}; template -class axis_iterator - : public iterator_facade, - detail::axis_iterator_value, - random_access_traversal_tag> { +using axis_iterator_value = std::pair< + int, typename conditional< + is_reference::value, + cref::type>, + typename Axis::bin_type>::type>; +} // namespace detail + +template +class axis_iterator : public iterator_facade, + detail::axis_iterator_value, + random_access_traversal_tag> { using value_type = detail::axis_iterator_value; + public: - explicit axis_iterator(const Axis &axis, int idx) - : axis_(axis) { value_.first = idx; } + explicit axis_iterator(const Axis &axis, int idx) : axis_(axis) { + value_.first = idx; + } private: void increment() noexcept { ++value_.first; } @@ -84,7 +80,7 @@ private: bool equal(const axis_iterator &other) const noexcept { return value_.first == other.value_.first; } - value_type& dereference() const { + value_type &dereference() const { value_.second = axis_[value_.first]; return value_; } @@ -204,40 +200,43 @@ private: }; namespace transform { -template struct identity { - static Value forward(Value v) { return v; } - static Value inverse(Value v) { return v; } - bool operator==(const identity&) const { return true; } +struct identity { + template static T forward(T v) { return v; } + template static T inverse(T v) { return v; } + bool operator==(const identity &) const { return true; } template void serialize(Archive &, unsigned) {} }; -template struct log { - static Value forward(Value v) { return std::log(v); } - static Value inverse(Value v) { return std::exp(v); } - bool operator==(const log&) const { return true; } +struct log { + template static T forward(T v) { return std::log(v); } + template static T inverse(T v) { return std::exp(v); } + bool operator==(const log &) const { return true; } template void serialize(Archive &, unsigned) {} }; -template struct sqrt { - static Value forward(Value v) { return std::sqrt(v); } - static Value inverse(Value v) { return v * v; } - bool operator==(const sqrt&) const { return true; } +struct sqrt { + template static T forward(T v) { return std::sqrt(v); } + template static T inverse(T v) { return v * v; } + bool operator==(const sqrt &) const { return true; } template void serialize(Archive &, unsigned) {} }; -template struct cos { - static Value forward(Value v) { return std::cos(v); } - static Value inverse(Value v) { return std::acos(v); } - bool operator==(const cos&) const { return true; } +struct cos { + template static T forward(T v) { return std::cos(v); } + template static T inverse(T v) { return std::acos(v); } + bool operator==(const cos &) const { return true; } template void serialize(Archive &, unsigned) {} }; -template struct pow { +struct pow { + pow() = default; pow(double exponent) : value(exponent) {} - Value forward(Value v) const { return std::pow(v, value); } - Value inverse(Value v) const { return std::pow(v, 1.0/value); } + template T forward(T v) const { return std::pow(v, value); } + template T inverse(T v) const { + return std::pow(v, 1.0 / value); + } double value = 1.0; - bool operator==(const pow& other) const { return value == other.value; } + bool operator==(const pow &other) const { return value == other.value; } template void serialize(Archive &, unsigned); }; } // namespace transform @@ -247,14 +246,13 @@ template struct pow { * The simplest and common binning strategy. * Very fast. Binning is a O(1) operation. */ -template class Transform = transform::identity> +template class regular : public axis_base, boost::operators> { - using transform = Transform; public: using value_type = RealType; using bin_type = interval; + using transform_type = Transform; using const_iterator = axis_iterator; /** Construct axis with n bins over range [min, max). @@ -267,16 +265,15 @@ public: * \param trans arguments passed to the transform. */ regular(unsigned n, value_type min, value_type max, - string_view label = string_view(), - bool uoflow = true, transform trans = transform()) - : axis_base(n, label, uoflow), - min_(trans.forward(min)), - delta_((trans.forward(max) - trans.forward(min)) / n), - trans_(trans) - { + string_view label = string_view(), bool uoflow = true, + transform_type trans = transform_type()) + : axis_base(n, label, uoflow), min_(trans.forward(min)), + delta_((trans.forward(max) - trans.forward(min)) / n), trans_(trans) { if (!(min < max)) { throw std::logic_error("min < max required"); } + BOOST_ASSERT(!std::isnan(min_)); + BOOST_ASSERT(!std::isnan(delta_)); } regular() = default; @@ -293,7 +290,7 @@ public: } /// Returns the starting edge of the bin. - bin_type operator[](int idx) const { + bin_type operator[](int idx) const noexcept { auto eval = [this](int i) { const auto n = size(); if (i < 0) @@ -301,28 +298,29 @@ public: if (i > n) return trans_.inverse(std::numeric_limits::infinity()); const auto z = value_type(i) / n; - return trans_.inverse((1.0 - z) * min_ + - z * (min_ + delta_ * n)); + return trans_.inverse((1.0 - z) * min_ + z * (min_ + delta_ * n)); }; - return {eval(idx), eval(idx+1)}; + return {eval(idx), eval(idx + 1)}; } - bool operator==(const regular &o) const { + bool operator==(const regular &o) const noexcept { return axis_base::operator==(o) && min_ == o.min_ && delta_ == o.delta_ && trans_ == o.trans_; } - const_iterator begin() const { + const_iterator begin() const noexcept { return const_iterator(*this, uoflow() ? -1 : 0); } - const_iterator end() const { + const_iterator end() const noexcept { return const_iterator(*this, uoflow() ? size() + 1 : size()); } + const transform_type &transform() const noexcept { return trans_; } + private: value_type min_ = 0.0, delta_ = 1.0; - transform trans_; + transform_type trans_; friend class ::boost::serialization::access; template void serialize(Archive &, unsigned); @@ -374,7 +372,7 @@ public: const value_type z = value_type(i) / size(); return z * perimeter_ + phase_; }; - return {eval(idx), eval(idx+1)}; + return {eval(idx), eval(idx + 1)}; } bool operator==(const circular &o) const { @@ -467,7 +465,7 @@ public: } return x_[i]; }; - return {eval(idx), eval(idx+1)}; + return {eval(idx), eval(idx + 1)}; } bool operator==(const variable &o) const { @@ -531,9 +529,7 @@ public: } /// Returns the integer that is mapped to the bin index. - bin_type operator[](int idx) const { - return {min_ + idx, min_ + idx + 1}; - } + bin_type operator[](int idx) const { return {min_ + idx, min_ + idx + 1}; } bool operator==(const integer &o) const { return axis_base::operator==(o) && min_ == o.min_; @@ -562,11 +558,13 @@ private: * Binning is a O(1) operation. The value type must be hashable. */ template -class category : public axis_base, boost::operators> { +class category : public axis_base, + boost::operators> { using map_type = bimap; + public: using value_type = T; - using bin_type = const value_type&; + using bin_type = const value_type &; using const_iterator = axis_iterator>; category() = default; @@ -575,22 +573,18 @@ public: * * \param seq sequence of unique values. */ - category(std::initializer_list seq, - string_view label = string_view()) - : axis_base(seq.size(), label) - { + category(std::initializer_list seq, string_view label = string_view()) + : axis_base(seq.size(), label) { int index = 0; - for (const auto& x : seq) + for (const auto &x : seq) map_.insert({x, index++}); if (index == 0) throw std::logic_error("sequence is empty"); } template - category(Iterator begin, Iterator end, - string_view label = string_view()) - : axis_base(std::distance(begin, end), label) - { + category(Iterator begin, Iterator end, string_view label = string_view()) + : axis_base(std::distance(begin, end), label) { int index = 0; while (begin != end) map_.insert({*begin++, index++}); @@ -600,7 +594,7 @@ public: /// Returns the bin index for the passed argument. /// Performs a range check. - inline int index(const value_type& x) const noexcept { + inline int index(const value_type &x) const noexcept { auto it = map_.left.find(x); if (it == map_.left.end()) return size(); @@ -633,8 +627,11 @@ private: } // namespace axis using builtin_axes = - mpl::vector, axis::circular<>, axis::variable<>, - axis::integer<>, axis::category>; + mpl::vector, axis::regular, + axis::regular, + axis::regular, + axis::regular, axis::circular<>, + axis::variable<>, axis::integer<>, axis::category<>>; } // namespace histogram } // namespace boost diff --git a/include/boost/histogram/axis_ostream_operators.hpp b/include/boost/histogram/axis_ostream_operators.hpp index cbbb6731..dd5e0753 100644 --- a/include/boost/histogram/axis_ostream_operators.hpp +++ b/include/boost/histogram/axis_ostream_operators.hpp @@ -9,16 +9,43 @@ #include #include +#include +#include #include #include namespace boost { namespace histogram { + namespace axis { -template class Transform> -inline std::ostream &operator<<(std::ostream &os, const regular &a) { - os << "regular(" << a.size() << ", " << a[0].lower() << ", " << a[a.size()].lower(); +namespace detail { +inline string_view to_string(int) { return {"int", 3}; } +inline string_view to_string(double) { return {"double", 6}; } +inline string_view to_string(const transform::identity &) { return {}; } +inline string_view to_string(const transform::log &) { return {"log", 3}; } +inline string_view to_string(const transform::sqrt &) { return {"sqrt", 4}; } +inline string_view to_string(const transform::cos &) { return {"cos", 3}; } +inline std::string to_string(const transform::pow &p) { + std::string s("pow("); + s += lexical_cast(p.value); + s += ")"; + return s; +} +} // namespace detail + +template +std::ostream &operator<<(std::ostream &os, const interval &i) { + os << "interval_" << detail::to_string(T()) << "(" << i.lower() << ", " + << i.upper() << ")"; + return os; +} + +template +inline std::ostream &operator<<(std::ostream &os, + const regular &a) { + os << "regular(" << a.size() << ", " << a[0].lower() << ", " + << a[a.size()].lower(); if (!a.label().empty()) { os << ", label="; ::boost::histogram::detail::escape(os, a.label()); @@ -26,6 +53,11 @@ inline std::ostream &operator<<(std::ostream &os, const regular &a) { } template <> -inline std::ostream &operator<<(std::ostream &os, const category &a) { +inline std::ostream &operator<<(std::ostream &os, + const category &a) { os << "category("; for (int i = 0; i < a.size(); ++i) { ::boost::histogram::detail::escape(os, a[i]); diff --git a/include/boost/histogram/detail/axis_visitor.hpp b/include/boost/histogram/detail/axis_visitor.hpp index 59c5076b..ee63562b 100644 --- a/include/boost/histogram/detail/axis_visitor.hpp +++ b/include/boost/histogram/detail/axis_visitor.hpp @@ -7,19 +7,19 @@ #ifndef _BOOST_HISTOGARM_AXIS_VISITOR_HPP_ #define _BOOST_HISTOGARM_AXIS_VISITOR_HPP_ -#include #include #include #include #include #include #include +#include #include #include +#include #include #include #include -#include namespace boost { namespace histogram { @@ -43,18 +43,18 @@ template struct index : public static_visitor { template int operator()(const A &a) const { return a.index(v); } }; -struct bin : public static_visitor> { - using double_interval = interval; +struct bin : public static_visitor> { + using double_interval = axis::interval; const int i; bin(const int v) : i(v) {} - template - double_interval operator()(const A &a) const { + template double_interval operator()(const A &a) const { return impl(is_convertible(), - std::forward(a[i])); } - template - double_interval impl(true_type, B && b) const { return b; } - template - double_interval impl(false_type, B &&) const { + std::forward(a[i])); + } + template double_interval impl(true_type, B &&b) const { + return b; + } + template double_interval impl(false_type, B &&) const { throw std::runtime_error("cannot convert bin_type to interval"); } }; diff --git a/include/boost/histogram/interval.hpp b/include/boost/histogram/interval.hpp index 0e8d7507..4bc9cf07 100644 --- a/include/boost/histogram/interval.hpp +++ b/include/boost/histogram/interval.hpp @@ -9,39 +9,38 @@ #include -namespace boost { namespace histogram { +namespace boost { +namespace histogram { +namespace axis { -template -class interval { +template class interval { public: interval() = default; - interval(const interval&) = default; - interval& operator=(const interval&) = default; - interval(interval&&) = default; - interval& operator=(interval&&) = default; + interval(const interval &) = default; + interval &operator=(const interval &) = default; + interval(interval &&) = default; + interval &operator=(interval &&) = default; + + interval(const T &x, const T &y) : a(x), b(y) {} + interval(T &&x, T &&y) : a(std::move(x)), b(std::move(y)) {} template - interval(U&& x, U&& y) : a(std::forward(x)), b(std::forward(y)) {} + interval(const interval &i) : a(i.lower()), b(i.upper()) {} - template - interval(const interval& i) : a(i.lower()), b(i.upper()) {} + const T &lower() const noexcept { return a; } + const T &upper() const noexcept { return b; } - template - interval(interval&& i) : a(i.lower()), b(i.upper()) {} - - const T& lower() const noexcept { return a; } - const T& upper() const noexcept { return b; } - - bool operator==(const interval& i) const noexcept { + bool operator==(const interval &i) const noexcept { return a == i.a && b == i.b; } - bool operator!=(const interval& i) const noexcept { - return !operator==(i); - } + bool operator!=(const interval &i) const noexcept { return !operator==(i); } + private: T a, b; }; -}} +} // namespace axis +} // namespace histogram +} // namespace boost #endif diff --git a/include/boost/histogram/serialization.hpp b/include/boost/histogram/serialization.hpp index a24f4256..ed922ac7 100644 --- a/include/boost/histogram/serialization.hpp +++ b/include/boost/histogram/serialization.hpp @@ -133,14 +133,13 @@ void axis_base::serialize(Archive &ar, unsigned /* version */) { } namespace transform { - template - template - void pow::serialize(Archive& ar, unsigned /* version */) { - ar & value; - } +template +void pow::serialize(Archive &ar, unsigned /* version */) { + ar &value; } +} // namespace transform -template class Transform> +template template void regular::serialize(Archive &ar, unsigned /* version */) { diff --git a/include/boost/histogram/utility.hpp b/include/boost/histogram/utility.hpp index 1d761f89..1fd3f560 100644 --- a/include/boost/histogram/utility.hpp +++ b/include/boost/histogram/utility.hpp @@ -34,13 +34,13 @@ inline int index(const boost::variant &a, const V v) { return apply_visitor(detail::index(v), a); } -template -inline typename A::bin_type bin(const A &a, const int i) { +template inline typename A::bin_type bin(const A &a, const int i) { return a[i]; } template -inline interval bin(const boost::variant &a, const int i) { +inline axis::interval bin(const boost::variant &a, + const int i) { return apply_visitor(detail::bin(i), a); } diff --git a/src/python/axis.cpp b/src/python/axis.cpp index 08c804ca..6dcedd73 100644 --- a/src/python/axis.cpp +++ b/src/python/axis.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef HAVE_NUMPY #include namespace np = boost::python::numpy; @@ -21,12 +22,17 @@ namespace np = boost::python::numpy; #include #include - namespace boost { namespace histogram { namespace { +template python::str generic_repr(const T &t) { + std::ostringstream os; + os << t; + return os.str().c_str(); +} + python::object variable_init(python::tuple args, python::dict kwargs) { using namespace python; @@ -42,14 +48,14 @@ python::object variable_init(python::tuple args, python::dict kwargs) { v.push_back(extract(args[i])); } - std::string label; + string_view label; bool uoflow = true; while (len(kwargs) > 0) { python::tuple kv = kwargs.popitem(); - std::string k = extract(kv[0]); + string_view k = extract(kv[0])(); object v = kv[1]; if (k == "label") - label = extract(v); + label = extract(v)(); else if (k == "uoflow") uoflow = extract(v); else { @@ -74,13 +80,13 @@ python::object category_init(python::tuple args, python::dict kwargs) { throw_error_already_set(); } - std::string label; + string_view label; while (len(kwargs) > 0) { python::tuple kv = kwargs.popitem(); - std::string k = extract(kv[0]); + string_view k = extract(kv[0])(); object v = kv[1]; if (k == "label") - label = extract(v); + label = extract(v)(); else { std::stringstream s; s << "keyword " << k << " not recognized"; @@ -112,16 +118,8 @@ template <> python::object axis_getitem(const axis::category<> &a, int i) { return python::object(a[i]); } -template std::string axis_repr(const T &t) { - std::ostringstream os; - os << t; - return os.str(); -} - template void axis_set_label(T& t, python::str s) { - const char* d = python::extract(s); - const auto n = python::len(s); - t.label(string_view(d, n)); + t.label(python::extract(s)()); } template python::str axis_get_label(const T& t) { @@ -181,7 +179,7 @@ struct axis_suite : public python::def_visitor> { ":param integer i: bin index" "\n:returns: bin corresponding to index", python::args("self", "i")); - cl.def("__repr__", axis_repr, + cl.def("__repr__", generic_repr, ":returns: string representation of this axis", python::arg("self")); cl.def(python::self == python::self); #ifdef HAVE_NUMPY @@ -190,11 +188,40 @@ struct axis_suite : public python::def_visitor> { } }; +python::object make_regular(unsigned bin, double lower, double upper, + python::str pylabel, bool uoflow, + python::str pytrans) +{ + using namespace ::boost::python; + string_view label(extract(pylabel)(), len(pylabel)); + string_view trans(extract(pytrans)(), len(pytrans)); + if (trans.empty()) + return object(axis::regular<>(bin, lower, upper, label, uoflow)); + else if (trans == "log") + return object(axis::regular( + bin, lower, upper, label, uoflow)); + else if (trans == "sqrt") + return object(axis::regular( + bin, lower, upper, label, uoflow)); + else if (trans == "cos") + return object(axis::regular( + bin, lower, upper, label, uoflow)); + else if (trans.substr(0, 3) == "pow") { + const double val = lexical_cast(trans.substr(4, trans.size()-1)); + return object(axis::regular( + bin, lower, upper, label, uoflow, axis::transform::pow(val))); + } + PyErr_SetString(PyExc_KeyError, "transform signature not recognized"); + throw_error_already_set(); + return object(); +} + } // namespace void register_axis_types() { - using namespace python; - using python::arg; + using namespace ::boost::python; + using namespace ::boost::histogram::axis; + using ::boost::python::arg; // resolve ambiguity docstring_options dopt(true, true, false); class_>( @@ -206,6 +233,7 @@ void register_axis_types() { .add_property("upper", make_function(&interval::upper, return_value_policy())) + .def("__repr__", generic_repr>) ; class_>( @@ -217,53 +245,69 @@ void register_axis_types() { .add_property("upper", make_function(&interval::upper, return_value_policy())) + .def("__repr__", generic_repr>) ; - class_>( - "regular", - "An axis for real-valued data and bins of equal width." - "\nBinning is a O(1) operation.", - no_init) - .def(init( - (arg("self"), arg("bin"), arg("lower"), arg("upper"), - arg("label") = std::string(), arg("uoflow") = true))) - .def(axis_suite>()); +#define BOOST_HISTOGRAM_REGULAR_AXIS_PYTHON_CLASS(x) \ + class_>( \ + "regular_"#x, \ + "An axis for real-valued data and bins of equal width." \ + "\nBinning is a O(1) operation.", \ + no_init) \ + .def(axis_suite>()) - class_>( + BOOST_HISTOGRAM_REGULAR_AXIS_PYTHON_CLASS(identity); + BOOST_HISTOGRAM_REGULAR_AXIS_PYTHON_CLASS(log); + BOOST_HISTOGRAM_REGULAR_AXIS_PYTHON_CLASS(sqrt); + BOOST_HISTOGRAM_REGULAR_AXIS_PYTHON_CLASS(cos); + BOOST_HISTOGRAM_REGULAR_AXIS_PYTHON_CLASS(pow); + + def("regular", make_regular, + "An axis for real-valued data and bins of equal width." + "\nOptionally, a monotonic transform can be selected from" + "\na predefined set, which mediates between the data space" + "\nand the axis space. For example, one can create an axis" + "\nwith logarithmic instead of normal linear steps." + "\nBinning is a O(1) operation.", + (arg("bin"), arg("lower"), arg("upper"), + arg("label") = str(), arg("uoflow") = true, + arg("trans") = str())); + + class_>( "circular", "An axis for real-valued angles." "\nThere are no overflow/underflow bins for this axis," "\nsince the axis is circular and wraps around after reaching" "\nthe perimeter value. Binning is a O(1) operation.", no_init) - .def(init( + .def(init( (arg("self"), arg("bin"), arg("phase") = 0.0, arg("perimeter") = math::double_constants::two_pi, arg("label") = std::string()))) - .def(axis_suite>()); + .def(axis_suite>()); - class_>( + class_>( "variable", "An axis for real-valued data and bins of varying width." "\nBinning is a O(log(N)) operation. If speed matters and" "\nthe problem domain allows it, prefer a regular axis.", no_init) .def("__init__", raw_function(variable_init)) - .def(init &>()) - .def(axis_suite>()); + .def(init &>()) + .def(axis_suite>()); - class_>( + class_>( "integer", "An axis for a contiguous range of integers with bins" "\nthat are one integer wide. Faster than a regular axis." "\nBinning is a O(1) operation.", no_init) - .def(init( + .def(init( (arg("self"), arg("lower"), arg("upper"), arg("label") = std::string(), arg("uoflow") = true))) - .def(axis_suite>()); + .def(axis_suite>()); - class_>( + class_>( "category", "An axis for set of unique integer values. Each value is mapped to" "\na corresponding bin, following the order of the arguments in" @@ -271,8 +315,8 @@ void register_axis_types() { "\nBinning is a O(1) operation.", no_init) .def("__init__", raw_function(category_init)) - .def(init &>()) - .def(axis_suite>()); + .def(init &>()) + .def(axis_suite>()); } } } diff --git a/test/axis_test.cpp b/test/axis_test.cpp index 15e7153b..099ea8e5 100644 --- a/test/axis_test.cpp +++ b/test/axis_test.cpp @@ -20,15 +20,6 @@ #define BOOST_TEST_NOT(expr) BOOST_TEST(!(expr)) #define BOOST_TEST_IS_CLOSE(a, b, eps) BOOST_TEST(std::abs(a - b) < eps) -namespace boost { namespace histogram { -template -std::ostream& operator<<(std::ostream& os, const interval& i) -{ - os << "[" << i.lower() << ", " << i.upper() << ")"; - return os; -} -}} - template void test_axis_iterator(const Axis &a, int begin, int end) { for (const auto &bin : a) { @@ -215,7 +206,7 @@ int main() { // iterators { - enum {A, B, C}; + enum { A, B, C }; test_axis_iterator(axis::regular<>(5, 0, 1, "", false), 0, 5); test_axis_iterator(axis::regular<>(5, 0, 1, "", true), -1, 6); test_axis_iterator(axis::circular<>(5, 0, 1, ""), 0, 5); @@ -251,9 +242,11 @@ int main() { // axis_t_streamable { - enum {A, B, C}; + enum { A, B, C }; std::vector axes; - axes.push_back(axis::regular<>{2, -1, 1, "regular", false}); + axes.push_back(axis::regular<>{2, -1, 1, "regular1"}); + axes.push_back(axis::regular{ + 2, 1, 10, "regular2", false}); axes.push_back(axis::circular<>{4, 0.1, 1.0, "polar"}); axes.push_back(axis::variable<>{{-1, 0, 1}, "variable", false}); axes.push_back(axis::category<>{{A, B, C}, "category"}); @@ -262,17 +255,19 @@ int main() { for (const auto &a : axes) { os << a; } - const std::string ref = "regular(2, -1, 1, label='regular', uoflow=False)" - "circular(4, phase=0.1, perimeter=1, label='polar')" - "variable(-1, 0, 1, label='variable', uoflow=False)" - "category(0, 1, 2, label='category')" - "integer(-1, 1, label='integer', uoflow=False)"; + const std::string ref = + "regular(2, -1, 1, label='regular1')" + "regular(2, 1, 10, label='regular2', uoflow=False, trans='log')" + "circular(4, phase=0.1, perimeter=1, label='polar')" + "variable(-1, 0, 1, label='variable', uoflow=False)" + "category(0, 1, 2, label='category')" + "integer(-1, 1, label='integer', uoflow=False)"; BOOST_TEST_EQ(os.str(), ref); } // axis_t_equal_comparable { - enum {A, B, C}; + enum { A, B, C }; std::vector axes; axes.push_back(axis::regular<>{2, -1, 1}); axes.push_back(axis::circular<>{4}); @@ -289,19 +284,16 @@ int main() { // sequence equality { - enum {A, B, C}; + enum { A, B, C }; std::vector, axis::variable<>, axis::category<>, axis::integer<>>> std_vector1 = {axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1}, axis::category<>{A, B, C}}; std::vector< - boost::variant< - axis::regular<>, axis::variable<>, axis::category<> - > - > - std_vector2 = {axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1}, - axis::category<>{{A, B, C}}}; + boost::variant, axis::variable<>, axis::category<>>> + std_vector2 = {axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1}, + axis::category<>{{A, B, C}}}; std::vector, axis::variable<>>> std_vector3 = {axis::variable<>{-1, 0, 1}, axis::regular<>{2, -1, 1}}; @@ -333,7 +325,7 @@ int main() { // sequence assign { - enum {A, B, C, D}; + enum { A, B, C, D }; std::vector, axis::variable<>, axis::category<>, axis::integer<>>> std_vector1 = {axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1}, diff --git a/test/histogram_test.cpp b/test/histogram_test.cpp index f56b1985..9fc47cd0 100644 --- a/test/histogram_test.cpp +++ b/test/histogram_test.cpp @@ -115,7 +115,7 @@ template void run_tests() { // init_5 { - enum {A, B, C}; + enum { A, B, C }; auto h = make_histogram>( Type(), axis::regular<>{3, -1, 1}, axis::integer<>{-1, 2}, axis::circular<>{3}, axis::variable<>{-1, 0, 1},