clang-format everything

This commit is contained in:
Hans Dembinski 2018-07-21 17:27:18 +02:00
parent 47d4d85301
commit d4dbae92f5
53 changed files with 783 additions and 907 deletions

View File

@ -11,9 +11,7 @@ int main(int, char**) {
create a static 1d-histogram with an axis that has 6 equidistant create a static 1d-histogram with an axis that has 6 equidistant
bins on the real line from -1.0 to 2.0, and label it as "x" bins on the real line from -1.0 to 2.0, and label it as "x"
*/ */
auto h = bh::make_static_histogram( auto h = bh::make_static_histogram(bh::axis::regular<>(6, -1.0, 2.0, "x"));
bh::axis::regular<>(6, -1.0, 2.0, "x")
);
// fill histogram with data, typically this happens in a loop // fill histogram with data, typically this happens in a loop
// STL algorithms are supported // STL algorithms are supported
@ -56,13 +54,10 @@ int main(int, char**) {
std::cout.setf(std::ios_base::fixed); std::cout.setf(std::ios_base::fixed);
for (auto it = h.begin(); it != h.end(); ++it) { for (auto it = h.begin(); it != h.end(); ++it) {
const auto bin = it.bin(0_c); const auto bin = it.bin(0_c);
std::cout << "bin " << it.idx(0) << " x in [" std::cout << "bin " << it.idx(0) << " x in [" << std::setprecision(1)
<< std::setprecision(1) << std::setw(4) << bin.lower() << ", " << std::setw(4)
<< std::setw(4) << bin.lower() << ", " << bin.upper() << "): " << std::setprecision(1) << it->value()
<< std::setw(4) << bin.upper() << "): " << " +/- " << std::setprecision(3) << std::sqrt(it->variance())
<< std::setprecision(1)
<< it->value() << " +/- "
<< std::setprecision(3) << std::sqrt(it->variance())
<< std::endl; << std::endl;
} }

View File

@ -8,10 +8,8 @@ namespace bh = boost::histogram;
int main() { int main() {
// make histogram with 2 x 2 = 4 bins (not counting under-/overflow bins) // make histogram with 2 x 2 = 4 bins (not counting under-/overflow bins)
auto h = bh::make_static_histogram( auto h = bh::make_static_histogram(bh::axis::regular<>(2, -1, 1),
bh::axis::regular<>(2, -1, 1), bh::axis::regular<>(2, 2, 4));
bh::axis::regular<>(2, 2, 4)
);
h(bh::weight(1), -0.5, 2.5); // bin index 0, 0 h(bh::weight(1), -0.5, 2.5); // bin index 0, 0
h(bh::weight(2), -0.5, 3.5); // bin index 0, 1 h(bh::weight(2), -0.5, 3.5); // bin index 0, 1
@ -19,19 +17,14 @@ int main() {
h(bh::weight(4), 0.5, 3.5); // bin index 1, 1 h(bh::weight(4), 0.5, 3.5); // bin index 1, 1
// access count value, number of indices must match number of axes // access count value, number of indices must match number of axes
std::cout << h.at(0, 0).value() << " " std::cout << h.at(0, 0).value() << " " << h.at(0, 1).value() << " "
<< h.at(0, 1).value() << " " << h.at(1, 0).value() << " " << h.at(1, 1).value() << std::endl;
<< h.at(1, 0).value() << " "
<< h.at(1, 1).value()
<< std::endl;
// prints: 1 2 3 4 // prints: 1 2 3 4
// access count variance, number of indices must match number of axes // access count variance, number of indices must match number of axes
std::cout << h.at(0, 0).variance() << " " std::cout << h.at(0, 0).variance() << " " << h.at(0, 1).variance() << " "
<< h.at(0, 1).variance() << " " << h.at(1, 0).variance() << " " << h.at(1, 1).variance()
<< h.at(1, 0).variance() << " "
<< h.at(1, 1).variance()
<< std::endl; << std::endl;
// prints: 1 4 9 16 // prints: 1 4 9 16

View File

@ -8,8 +8,7 @@ int main() {
// create a 2d-histogram with an "age" and an "income" axis // create a 2d-histogram with an "age" and an "income" axis
auto h = bh::make_static_histogram( auto h = bh::make_static_histogram(
bh::axis::regular<>(20, 0, 100, "age in years"), bh::axis::regular<>(20, 0, 100, "age in years"),
bh::axis::regular<>(20, 0, 100, "yearly income in $1000") bh::axis::regular<>(20, 0, 100, "yearly income in $1000"));
);
// do something with h // do something with h
} }

View File

@ -6,7 +6,8 @@ namespace bh = boost::histogram;
int main() { int main() {
// create a 1d-histogram for dice throws with integer values from 1 to 6 // create a 1d-histogram for dice throws with integer values from 1 to 6
auto h = bh::make_static_histogram(bh::axis::integer<>(1, 7, "eyes", bh::axis::uoflow::off)); auto h = bh::make_static_histogram(
bh::axis::integer<>(1, 7, "eyes", bh::axis::uoflow::off));
// do something with h // do something with h
} }

View File

@ -14,9 +14,7 @@ struct custom_axis : public bh::axis::integer<> {
// the customization point // the customization point
// - accept const char* and convert to int // - accept const char* and convert to int
// - then call index method of base class // - then call index method of base class
int index(value_type s) const { int index(value_type s) const { return integer::index(std::atoi(s)); }
return integer::index(std::atoi(s));
}
}; };
int main() { int main() {
@ -28,8 +26,7 @@ int main() {
for (auto xi : h.axis()) { for (auto xi : h.axis()) {
std::cout << "bin " << xi.idx() << " [" << xi.lower() << ", " std::cout << "bin " << xi.idx() << " [" << xi.lower() << ", "
<< xi.upper() << ") " << h.at(xi).value() << xi.upper() << ") " << h.at(xi).value() << std::endl;
<< std::endl;
} }
/* prints: /* prints:

View File

@ -8,8 +8,7 @@ namespace bh = boost::histogram;
int main() { int main() {
// create static histogram with array_storage, using int as counter type // create static histogram with array_storage, using int as counter type
auto h = bh::make_static_histogram_with<bh::array_storage<int>>( auto h = bh::make_static_histogram_with<bh::array_storage<int>>(
bh::axis::regular<>(10, 0, 1) bh::axis::regular<>(10, 0, 1));
);
// do something with h // do something with h
} }

View File

@ -1,8 +1,8 @@
//[ guide_fill_histogram //[ guide_fill_histogram
#include <boost/histogram.hpp> #include <boost/histogram.hpp>
#include <vector>
#include <utility> #include <utility>
#include <vector>
namespace bh = boost::histogram; namespace bh = boost::histogram;
@ -23,14 +23,13 @@ int main() {
// functional-style processing is also supported // functional-style processing is also supported
std::vector<std::pair<int, double>> input_data{ std::vector<std::pair<int, double>> input_data{
{0, 1.2}, {2, 3.4}, {4, 5.6} {0, 1.2}, {2, 3.4}, {4, 5.6}};
};
// Note that std::for_each takes the functor by value, thus it makes a // Note that std::for_each takes the functor by value, thus it makes a
// potentially expensive copy of your histogram. Passing freshly created // potentially expensive copy of your histogram. Passing freshly created
// histograms is ok, though, because of return-value-optimization // histograms is ok, though, because of return-value-optimization
auto h2 = std::for_each(input_data.begin(), input_data.end(), auto h2 =
bh::make_static_histogram( std::for_each(input_data.begin(), input_data.end(),
bh::axis::integer<>(0, 4), bh::make_static_histogram(bh::axis::integer<>(0, 4),
bh::axis::regular<>(10, 0, 5))); bh::axis::regular<>(10, 0, 5)));
// h is filled // h is filled
} }

View File

@ -41,10 +41,10 @@ int main() {
// note: special effect of multiplication on counter variance // note: special effect of multiplication on counter variance
auto h = bh::make_static_histogram(bh::axis::regular<>(2, -1, 1)); auto h = bh::make_static_histogram(bh::axis::regular<>(2, -1, 1));
h(-0.5); // counts are: 1 0 h(-0.5); // counts are: 1 0
std::cout << "value " << (2 * h).at(0).value() std::cout << "value " << (2 * h).at(0).value() << " "
<< " " << (h + h).at(0).value() << "\n" << (h + h).at(0).value() << "\n"
<< "variance " << (2 * h).at(0).variance() << "variance " << (2 * h).at(0).variance() << " "
<< " " << (h + h).at(0).variance() << std::endl; << (h + h).at(0).variance() << std::endl;
// equality operator also checks variances, so the statement is false // equality operator also checks variances, so the statement is false
std::cout << (h + h == 2 * h) << std::endl; std::cout << (h + h == 2 * h) << std::endl;
/* prints: /* prints:

View File

@ -7,10 +7,10 @@ namespace bh = boost::histogram;
// example of a generic function for histograms, this one sums all entries // example of a generic function for histograms, this one sums all entries
template <typename... Ts> template <typename... Ts>
typename bh::histogram<Ts...>::element_type sum(const bh::histogram<Ts...>& h) { typename bh::histogram<Ts...>::element_type sum(
const bh::histogram<Ts...>& h) {
auto result = typename bh::histogram<Ts...>::element_type(0); auto result = typename bh::histogram<Ts...>::element_type(0);
for (auto x : h) for (auto x : h) result += x;
result += x;
return result; return result;
} }
@ -32,15 +32,12 @@ int main() {
reduce does not remove counts; returned histograms are summed over reduce does not remove counts; returned histograms are summed over
the removed axes, so h, hr0, and hr1 have same number of total counts the removed axes, so h, hr0, and hr1 have same number of total counts
*/ */
std::cout << sum(h).value() << " " std::cout << sum(h).value() << " " << sum(hr0).value() << " "
<< sum(hr0).value() << " "
<< sum(hr1).value() << std::endl; << sum(hr1).value() << std::endl;
// prints: 3 3 3 // prints: 3 3 3
for (auto yi : h.axis(1_c)) { for (auto yi : h.axis(1_c)) {
for (auto xi : h.axis(0_c)) { for (auto xi : h.axis(0_c)) { std::cout << h.at(xi, yi).value() << " "; }
std::cout << h.at(xi, yi).value() << " ";
}
std::cout << std::endl; std::cout << std::endl;
} }
// prints: 1 0 0 // prints: 1 0 0
@ -48,13 +45,11 @@ int main() {
// 0 1 0 // 0 1 0
// 0 0 1 // 0 0 1
for (auto xi : hr0.axis()) for (auto xi : hr0.axis()) std::cout << hr0.at(xi).value() << " ";
std::cout << hr0.at(xi).value() << " ";
std::cout << std::endl; std::cout << std::endl;
// prints: 1 1 1 // prints: 1 1 1
for (auto yi : hr1.axis()) for (auto yi : hr1.axis()) std::cout << hr1.at(yi).value() << " ";
std::cout << hr1.at(yi).value() << " ";
std::cout << std::endl; std::cout << std::endl;
// prints: 1 0 1 1 // prints: 1 0 1 1
} }

View File

@ -1,9 +1,9 @@
//[ guide_histogram_serialization //[ guide_histogram_serialization
#include <boost/histogram.hpp>
#include <boost/histogram/serialization.hpp> // includes serialization code
#include <boost/archive/text_iarchive.hpp> #include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_oarchive.hpp>
#include <boost/histogram.hpp>
#include <boost/histogram/serialization.hpp> // includes serialization code
#include <sstream> #include <sstream>
namespace bh = boost::histogram; namespace bh = boost::histogram;

View File

@ -17,8 +17,7 @@ int main() {
axis::circular<>(4, 0.1, 1.0, "polar"), axis::circular<>(4, 0.1, 1.0, "polar"),
axis::variable<>({-1, 0, 1}, "variable", axis::uoflow::off), axis::variable<>({-1, 0, 1}, "variable", axis::uoflow::off),
axis::category<>({A, B, C}, "category"), axis::category<>({A, B, C}, "category"),
axis::integer<>(-1, 1, "integer", axis::uoflow::off) axis::integer<>(-1, 1, "integer", axis::uoflow::off));
);
std::cout << h << std::endl; std::cout << h << std::endl;

View File

@ -1,7 +1,7 @@
//[ guide_mixed_cpp_python_part_cpp //[ guide_mixed_cpp_python_part_cpp
#include <boost/python.hpp>
#include <boost/histogram.hpp> #include <boost/histogram.hpp>
#include <boost/python.hpp>
namespace bh = boost::histogram; namespace bh = boost::histogram;
namespace bp = boost::python; namespace bp = boost::python;
@ -9,13 +9,10 @@ namespace bp = boost::python;
// function that runs in C++ and accepts reference to dynamic histogram // function that runs in C++ and accepts reference to dynamic histogram
void process(bh::dynamic_histogram<>& h) { void process(bh::dynamic_histogram<>& h) {
// fill histogram, in reality this would be arbitrarily complex code // fill histogram, in reality this would be arbitrarily complex code
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i) h(0.25 * i, i);
h(0.25 * i, i);
} }
// a minimal Python module, which exposes the process function to Python // a minimal Python module, which exposes the process function to Python
BOOST_PYTHON_MODULE(cpp_filler) { BOOST_PYTHON_MODULE(cpp_filler) { bp::def("process", process); }
bp::def("process", process);
}
//] //]

View File

@ -20,7 +20,8 @@ histogram<T, A, S>&& operator+(histogram<T, A, S>&& a,
} }
template <typename T, typename A, typename S> template <typename T, typename A, typename S>
histogram<T, A, S>&& operator+(histogram<T, A, S>&& a, histogram<T, A, S>&& b) { histogram<T, A, S>&& operator+(histogram<T, A, S>&& a,
histogram<T, A, S>&& b) {
a += b; a += b;
return std::move(a); return std::move(a);
} }

View File

@ -45,9 +45,7 @@ class base {
: size_(size), : size_(size),
shape_(size + static_cast<int>(uo)), shape_(size + static_cast<int>(uo)),
label_(label.begin(), label.end()) { label_(label.begin(), label.end()) {
if (size_ == 0) { if (size_ == 0) { throw std::invalid_argument("bins > 0 required"); }
throw std::invalid_argument("bins > 0 required");
}
} }
base() = default; base() = default;

View File

@ -32,7 +32,9 @@ class interval_view {
auto upper() const noexcept -> decltype(std::declval<Axis&>().lower(0)) { auto upper() const noexcept -> decltype(std::declval<Axis&>().lower(0)) {
return axis_.lower(idx_ + 1); return axis_.lower(idx_ + 1);
} }
typename Axis::value_type width() const noexcept { return upper() - lower(); } typename Axis::value_type width() const noexcept {
return upper() - lower();
}
bool operator==(const interval_view& rhs) const noexcept { bool operator==(const interval_view& rhs) const noexcept {
return idx_ == rhs.idx_ && axis_ == rhs.axis_; return idx_ == rhs.idx_ && axis_ == rhs.axis_;

View File

@ -14,12 +14,13 @@ namespace histogram {
namespace axis { namespace axis {
template <typename Axis> template <typename Axis>
class iterator_over : public iterator_facade<iterator_over<Axis>, class iterator_over
typename Axis::bin_type, : public iterator_facade<iterator_over<Axis>, typename Axis::bin_type,
random_access_traversal_tag, random_access_traversal_tag,
typename Axis::bin_type> { typename Axis::bin_type> {
public: public:
explicit iterator_over(const Axis& axis, int idx) : axis_(axis), idx_(idx) {} explicit iterator_over(const Axis& axis, int idx)
: axis_(axis), idx_(idx) {}
iterator_over(const iterator_over&) = default; iterator_over(const iterator_over&) = default;
iterator_over& operator=(const iterator_over&) = default; iterator_over& operator=(const iterator_over&) = default;
@ -43,10 +44,9 @@ class iterator_over : public iterator_facade<iterator_over<Axis>,
template <typename Axis> template <typename Axis>
class reverse_iterator_over class reverse_iterator_over
: public iterator_facade<reverse_iterator_over<Axis>, : public iterator_facade<
typename Axis::bin_type, reverse_iterator_over<Axis>, typename Axis::bin_type,
random_access_traversal_tag, random_access_traversal_tag, typename Axis::bin_type> {
typename Axis::bin_type> {
public: public:
explicit reverse_iterator_over(const Axis& axis, int idx) explicit reverse_iterator_over(const Axis& axis, int idx)
: axis_(axis), idx_(idx) {} : axis_(axis), idx_(idx) {}

View File

@ -20,15 +20,9 @@ namespace histogram {
namespace axis { namespace axis {
namespace detail { namespace detail {
inline string_view to_string(const transform::identity&) { inline string_view to_string(const transform::identity&) { return {}; }
return {}; inline string_view to_string(const transform::log&) { return {"_log", 4}; }
} inline string_view to_string(const transform::sqrt&) { return {"_sqrt", 5}; }
inline string_view to_string(const transform::log&) {
return {"_log", 4};
}
inline string_view to_string(const transform::sqrt&) {
return {"_sqrt", 5};
}
} // namespace detail } // namespace detail
template <typename T> template <typename T>
@ -52,36 +46,30 @@ inline std::ostream& operator<<(std::ostream& os,
os << ", label="; os << ", label=";
::boost::histogram::detail::escape(os, a.label()); ::boost::histogram::detail::escape(os, a.label());
} }
if (!a.uoflow()) { if (!a.uoflow()) { os << ", uoflow=False"; }
os << ", uoflow=False";
}
os << ")"; os << ")";
return os; return os;
} }
template <typename RealType> template <typename RealType>
inline std::ostream& operator<<( inline std::ostream& operator<<(
std::ostream& os, std::ostream& os, const regular<RealType, axis::transform::pow>& a) {
const regular<RealType, axis::transform::pow>& a) {
os << "regular_pow(" << a.size() << ", " << a[0].lower() << ", " os << "regular_pow(" << a.size() << ", " << a[0].lower() << ", "
<< a[a.size()].lower() << ", " << a.transform().power; << a[a.size()].lower() << ", " << a.transform().power;
if (!a.label().empty()) { if (!a.label().empty()) {
os << ", label="; os << ", label=";
::boost::histogram::detail::escape(os, a.label()); ::boost::histogram::detail::escape(os, a.label());
} }
if (!a.uoflow()) { if (!a.uoflow()) { os << ", uoflow=False"; }
os << ", uoflow=False";
}
os << ")"; os << ")";
return os; return os;
} }
template <typename RealType> template <typename RealType>
inline std::ostream& operator<<(std::ostream& os, const circular<RealType>& a) { inline std::ostream& operator<<(std::ostream& os,
const circular<RealType>& a) {
os << "circular(" << a.size(); os << "circular(" << a.size();
if (a.phase() != 0.0) { if (a.phase() != 0.0) { os << ", phase=" << a.phase(); }
os << ", phase=" << a.phase();
}
if (a.perimeter() != RealType(::boost::histogram::detail::two_pi)) { if (a.perimeter() != RealType(::boost::histogram::detail::two_pi)) {
os << ", perimeter=" << a.perimeter(); os << ", perimeter=" << a.perimeter();
} }
@ -94,18 +82,15 @@ inline std::ostream& operator<<(std::ostream& os, const circular<RealType>& a) {
} }
template <typename RealType> template <typename RealType>
inline std::ostream& operator<<(std::ostream& os, const variable<RealType>& a) { inline std::ostream& operator<<(std::ostream& os,
const variable<RealType>& a) {
os << "variable(" << a[0].lower(); os << "variable(" << a[0].lower();
for (int i = 1; i <= a.size(); ++i) { for (int i = 1; i <= a.size(); ++i) { os << ", " << a[i].lower(); }
os << ", " << a[i].lower();
}
if (!a.label().empty()) { if (!a.label().empty()) {
os << ", label="; os << ", label=";
::boost::histogram::detail::escape(os, a.label()); ::boost::histogram::detail::escape(os, a.label());
} }
if (!a.uoflow()) { if (!a.uoflow()) { os << ", uoflow=False"; }
os << ", uoflow=False";
}
os << ")"; os << ")";
return os; return os;
} }
@ -117,9 +102,7 @@ inline std::ostream& operator<<(std::ostream& os, const integer<IntType>& a) {
os << ", label="; os << ", label=";
::boost::histogram::detail::escape(os, a.label()); ::boost::histogram::detail::escape(os, a.label());
} }
if (!a.uoflow()) { if (!a.uoflow()) { os << ", uoflow=False"; }
os << ", uoflow=False";
}
os << ")"; os << ")";
return os; return os;
} }

View File

@ -127,11 +127,8 @@ class regular : public base,
* \param uoflow whether to add under-/overflow bins. * \param uoflow whether to add under-/overflow bins.
* \param trans arguments passed to the transform. * \param trans arguments passed to the transform.
*/ */
regular(unsigned n, regular(unsigned n, value_type lower, value_type upper,
value_type lower, string_view label = {}, axis::uoflow uo = axis::uoflow::on,
value_type upper,
string_view label = {},
axis::uoflow uo = axis::uoflow::on,
Transform trans = Transform()) Transform trans = Transform())
: base(n, label, uo), : base(n, label, uo),
Transform(trans), Transform(trans),
@ -177,8 +174,8 @@ class regular : public base,
bin_type operator[](int idx) const noexcept { return bin_type(idx, *this); } bin_type operator[](int idx) const noexcept { return bin_type(idx, *this); }
bool operator==(const regular& o) const noexcept { bool operator==(const regular& o) const noexcept {
return base::operator==(o) && Transform::operator==(o) && min_ == o.min_ && return base::operator==(o) && Transform::operator==(o) &&
delta_ == o.delta_; min_ == o.min_ && delta_ == o.delta_;
} }
/// Access properties of the transform. /// Access properties of the transform.
@ -213,8 +210,7 @@ class circular : public base, public iterator_mixin<circular<RealType>> {
* \param perimeter range after which value wraps around. * \param perimeter range after which value wraps around.
* \param label description of the axis. * \param label description of the axis.
*/ */
explicit circular(unsigned n, explicit circular(unsigned n, value_type phase = 0.0,
value_type phase = 0.0,
value_type perimeter = boost::histogram::detail::two_pi, value_type perimeter = boost::histogram::detail::two_pi,
string_view label = {}) string_view label = {})
: base(n, label, axis::uoflow::off), : base(n, label, axis::uoflow::off),
@ -230,7 +226,8 @@ class circular : public base, public iterator_mixin<circular<RealType>> {
/// Returns the bin index for the passed argument. /// Returns the bin index for the passed argument.
int index(value_type x) const noexcept { int index(value_type x) const noexcept {
const value_type z = (x - phase_) / perimeter_; const value_type z = (x - phase_) / perimeter_;
const int i = static_cast<int>(std::floor(z * base::size())) % base::size(); const int i =
static_cast<int>(std::floor(z * base::size())) % base::size();
return i + (i < 0) * base::size(); return i + (i < 0) * base::size();
} }
@ -275,8 +272,7 @@ class variable : public base, public iterator_mixin<variable<RealType>> {
* \param label description of the axis. * \param label description of the axis.
* \param uoflow whether to add under-/overflow bins. * \param uoflow whether to add under-/overflow bins.
*/ */
variable(std::initializer_list<value_type> x, variable(std::initializer_list<value_type> x, string_view label = {},
string_view label = {},
axis::uoflow uo = axis::uoflow::on) axis::uoflow uo = axis::uoflow::on)
: base(x.size() - 1, label, uo), x_(new value_type[x.size()]) { : base(x.size() - 1, label, uo), x_(new value_type[x.size()]) {
if (x.size() >= 2) { if (x.size() >= 2) {
@ -288,9 +284,7 @@ class variable : public base, public iterator_mixin<variable<RealType>> {
} }
template <typename Iterator> template <typename Iterator>
variable(Iterator begin, variable(Iterator begin, Iterator end, string_view label = {},
Iterator end,
string_view label = {},
axis::uoflow uo = axis::uoflow::on) axis::uoflow uo = axis::uoflow::on)
: base(std::distance(begin, end) - 1, label, uo), : base(std::distance(begin, end) - 1, label, uo),
x_(new value_type[std::distance(begin, end)]) { x_(new value_type[std::distance(begin, end)]) {
@ -299,7 +293,8 @@ class variable : public base, public iterator_mixin<variable<RealType>> {
} }
variable() = default; variable() = default;
variable(const variable& o) : base(o), x_(new value_type[base::size() + 1]) { variable(const variable& o)
: base(o), x_(new value_type[base::size() + 1]) {
std::copy(o.x_.get(), o.x_.get() + base::size() + 1, x_.get()); std::copy(o.x_.get(), o.x_.get() + base::size() + 1, x_.get());
} }
variable& operator=(const variable& o) { variable& operator=(const variable& o) {
@ -321,9 +316,7 @@ class variable : public base, public iterator_mixin<variable<RealType>> {
/// Returns the starting edge of the bin. /// Returns the starting edge of the bin.
value_type lower(int i) const noexcept { value_type lower(int i) const noexcept {
if (i < 0) { if (i < 0) { return -std::numeric_limits<value_type>::infinity(); }
return -std::numeric_limits<value_type>::infinity();
}
if (i > base::size()) { if (i > base::size()) {
return std::numeric_limits<value_type>::infinity(); return std::numeric_limits<value_type>::infinity();
} }
@ -333,9 +326,7 @@ class variable : public base, public iterator_mixin<variable<RealType>> {
bin_type operator[](int idx) const noexcept { return bin_type(idx, *this); } bin_type operator[](int idx) const noexcept { return bin_type(idx, *this); }
bool operator==(const variable& o) const noexcept { bool operator==(const variable& o) const noexcept {
if (!base::operator==(o)) { if (!base::operator==(o)) { return false; }
return false;
}
return std::equal(x_.get(), x_.get() + base::size() + 1, o.x_.get()); return std::equal(x_.get(), x_.get() + base::size() + 1, o.x_.get());
} }
@ -365,9 +356,7 @@ class integer : public base, public iterator_mixin<integer<IntType>> {
* \param label description of the axis. * \param label description of the axis.
* \param uoflow whether to add under-/overflow bins. * \param uoflow whether to add under-/overflow bins.
*/ */
integer(value_type lower, integer(value_type lower, value_type upper, string_view label = {},
value_type upper,
string_view label = {},
axis::uoflow uo = axis::uoflow::on) axis::uoflow uo = axis::uoflow::on)
: base(upper - lower, label, uo), min_(lower) { : base(upper - lower, label, uo), min_(lower) {
if (!(lower < upper)) { if (!(lower < upper)) {
@ -389,12 +378,8 @@ class integer : public base, public iterator_mixin<integer<IntType>> {
/// Returns lower edge of the integral bin. /// Returns lower edge of the integral bin.
value_type lower(int i) const noexcept { value_type lower(int i) const noexcept {
if (i < 0) { if (i < 0) { return -std::numeric_limits<value_type>::max(); }
return -std::numeric_limits<value_type>::max(); if (i > base::size()) { return std::numeric_limits<value_type>::max(); }
}
if (i > base::size()) {
return std::numeric_limits<value_type>::max();
}
return min_ + i; return min_ + i;
} }
@ -446,10 +431,8 @@ class category : public base, public iterator_mixin<category<T>> {
category(std::initializer_list<value_type> seq, string_view label = {}) category(std::initializer_list<value_type> seq, string_view label = {})
: base(seq.size(), label, axis::uoflow::off), map_(new map_type()) { : base(seq.size(), label, axis::uoflow::off), map_(new map_type()) {
int index = 0; int index = 0;
for (const auto& x : seq) for (const auto& x : seq) map_->insert({x, index++});
map_->insert({x, index++}); if (index == 0) throw std::invalid_argument("sequence is empty");
if (index == 0)
throw std::invalid_argument("sequence is empty");
} }
template <typename Iterator, template <typename Iterator,
@ -458,17 +441,14 @@ class category : public base, public iterator_mixin<category<T>> {
: base(std::distance(begin, end), label, axis::uoflow::off), : base(std::distance(begin, end), label, axis::uoflow::off),
map_(new map_type()) { map_(new map_type()) {
int index = 0; int index = 0;
while (begin != end) while (begin != end) map_->insert({*begin++, index++});
map_->insert({*begin++, index++}); if (index == 0) throw std::invalid_argument("iterator range is empty");
if (index == 0)
throw std::invalid_argument("iterator range is empty");
} }
/// Returns the bin index for the passed argument. /// Returns the bin index for the passed argument.
int index(const value_type& x) const noexcept { int index(const value_type& x) const noexcept {
auto it = map_->left.find(x); auto it = map_->left.find(x);
if (it == map_->left.end()) if (it == map_->left.end()) return base::size();
return base::size();
return it->second; return it->second;
} }

View File

@ -59,15 +59,13 @@ struct axes_assign_vecvar_tuple {
}; };
template <typename... Ts> template <typename... Ts>
inline bool axes_equal_impl(mp11::mp_true, inline bool axes_equal_impl(mp11::mp_true, const std::tuple<Ts...>& t,
const std::tuple<Ts...>& t,
const std::tuple<Ts...>& u) { const std::tuple<Ts...>& u) {
return t == u; return t == u;
} }
template <typename... Ts, typename... Us> template <typename... Ts, typename... Us>
inline bool axes_equal_impl(mp11::mp_false, inline bool axes_equal_impl(mp11::mp_false, const std::tuple<Ts...>&,
const std::tuple<Ts...>&,
const std::tuple<Us...>&) { const std::tuple<Us...>&) {
return false; return false;
} }
@ -75,14 +73,16 @@ inline bool axes_equal_impl(mp11::mp_false,
} // namespace } // namespace
template <typename... Ts, typename... Us> template <typename... Ts, typename... Us>
inline bool axes_equal(const std::tuple<Ts...>& t, const std::tuple<Us...>& u) { inline bool axes_equal(const std::tuple<Ts...>& t,
const std::tuple<Us...>& u) {
return axes_equal_impl( return axes_equal_impl(
mp11::mp_same<mp11::mp_list<Ts...>, mp11::mp_list<Us...>>(), t, u); mp11::mp_same<mp11::mp_list<Ts...>, mp11::mp_list<Us...>>(), t, u);
} }
template <typename... Ts, typename... Us> template <typename... Ts, typename... Us>
inline void axes_assign(std::tuple<Ts...>& t, const std::tuple<Us...>& u) { inline void axes_assign(std::tuple<Ts...>& t, const std::tuple<Us...>& u) {
static_assert(std::is_same<mp11::mp_list<Ts...>, mp11::mp_list<Us...>>::value, static_assert(
std::is_same<mp11::mp_list<Ts...>, mp11::mp_list<Us...>>::value,
"cannot assign incompatible axes"); "cannot assign incompatible axes");
t = u; t = u;
} }
@ -90,12 +90,11 @@ inline void axes_assign(std::tuple<Ts...>& t, const std::tuple<Us...>& u) {
template <typename... Ts, typename... Us> template <typename... Ts, typename... Us>
inline bool axes_equal(const std::tuple<Ts...>& t, inline bool axes_equal(const std::tuple<Ts...>& t,
const std::vector<axis::any<Us...>>& u) { const std::vector<axis::any<Us...>>& u) {
if (sizeof...(Ts) != u.size()) if (sizeof...(Ts) != u.size()) return false;
return false;
bool equal = true; bool equal = true;
auto fn = auto fn =
axes_equal_tuple_vecvar<std::tuple<Ts...>, std::vector<axis::any<Us...>>>( axes_equal_tuple_vecvar<std::tuple<Ts...>,
equal, t, u); std::vector<axis::any<Us...>>>(equal, t, u);
mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Ts)>>(fn); mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Ts)>>(fn);
return equal; return equal;
} }
@ -126,11 +125,9 @@ inline void axes_assign(std::vector<axis::any<Ts...>>& t,
template <typename... Ts, typename... Us> template <typename... Ts, typename... Us>
inline bool axes_equal(const std::vector<axis::any<Ts...>>& t, inline bool axes_equal(const std::vector<axis::any<Ts...>>& t,
const std::vector<axis::any<Us...>>& u) { const std::vector<axis::any<Us...>>& u) {
if (t.size() != u.size()) if (t.size() != u.size()) return false;
return false;
for (std::size_t i = 0; i < t.size(); ++i) { for (std::size_t i = 0; i < t.size(); ++i) {
if (t[i] != u[i]) if (t[i] != u[i]) return false;
return false;
} }
return true; return true;
} }
@ -138,9 +135,7 @@ inline bool axes_equal(const std::vector<axis::any<Ts...>>& t,
template <typename... Ts, typename... Us> template <typename... Ts, typename... Us>
inline void axes_assign(std::vector<axis::any<Ts...>>& t, inline void axes_assign(std::vector<axis::any<Ts...>>& t,
const std::vector<axis::any<Us...>>& u) { const std::vector<axis::any<Us...>>& u) {
for (std::size_t i = 0; i < t.size(); ++i) { for (std::size_t i = 0; i < t.size(); ++i) { t[i] = u[i]; }
t[i] = u[i];
}
} }
struct field_count_visitor : public static_visitor<void> { struct field_count_visitor : public static_visitor<void> {

View File

@ -7,8 +7,8 @@
#ifndef _BOOST_HISTOGRAM_DETAIL_INDEX_CACHE_HPP_ #ifndef _BOOST_HISTOGRAM_DETAIL_INDEX_CACHE_HPP_
#define _BOOST_HISTOGRAM_DETAIL_INDEX_CACHE_HPP_ #define _BOOST_HISTOGRAM_DETAIL_INDEX_CACHE_HPP_
#include <memory>
#include <cstddef> #include <cstddef>
#include <memory>
namespace boost { namespace boost {
namespace histogram { namespace histogram {
@ -62,8 +62,7 @@ struct index_cache {
} }
void operator()(std::size_t idx) { void operator()(std::size_t idx) {
if (idx == idx_) if (idx == idx_) return;
return;
idx_ = idx; idx_ = idx;
auto dim_ptr = dims_.get(); auto dim_ptr = dims_.get();
auto dim = dim_; auto dim = dim_;

View File

@ -32,8 +32,9 @@ struct index_mapper {
s1 *= ni; s1 *= ni;
++bi; ++bi;
} }
std::sort(dims.begin(), dims.end(), std::sort(dims.begin(), dims.end(), [](const dim& a, const dim& b) {
[](const dim& a, const dim& b) { return a.stride1 > b.stride1; }); return a.stride1 > b.stride1;
});
nfirst = s1; nfirst = s1;
} }

View File

@ -55,14 +55,12 @@ struct no_container_tag {};
template <typename T> template <typename T>
using classify_container = typename std::conditional< using classify_container = typename std::conditional<
is_static_container<T>::value, is_static_container<T>::value, static_container_tag,
static_container_tag,
typename std::conditional<is_dynamic_container<T>::value, typename std::conditional<is_dynamic_container<T>::value,
dynamic_container_tag, dynamic_container_tag,
no_container_tag>::type>::type; no_container_tag>::type>::type;
template <typename T, template <typename T, typename = decltype(std::declval<T&>().size(),
typename = decltype(std::declval<T&>().size(),
std::declval<T&>().increase(0), std::declval<T&>().increase(0),
std::declval<T&>()[0])> std::declval<T&>()[0])>
struct requires_storage {}; struct requires_storage {};
@ -72,10 +70,9 @@ template <typename T,
struct requires_iterator {}; struct requires_iterator {};
template <typename T> template <typename T>
using requires_axis = decltype(std::declval<T&>().size(), using requires_axis =
std::declval<T&>().shape(), decltype(std::declval<T&>().size(), std::declval<T&>().shape(),
std::declval<T&>().uoflow(), std::declval<T&>().uoflow(), std::declval<T&>().label(),
std::declval<T&>().label(),
std::declval<T&>()[0]); std::declval<T&>()[0]);
namespace { namespace {
@ -108,13 +105,11 @@ using mp_at_c = mp11::mp_at_c<rm_cv_ref<T>, D>;
template <typename T1, typename T2> template <typename T1, typename T2>
using copy_qualifiers = mp11::mp_if< using copy_qualifiers = mp11::mp_if<
std::is_rvalue_reference<T1>, std::is_rvalue_reference<T1>, T2&&,
T2&&,
mp11::mp_if< mp11::mp_if<
std::is_lvalue_reference<T1>, std::is_lvalue_reference<T1>,
mp11::mp_if<std::is_const<typename std::remove_reference<T1>::type>, mp11::mp_if<std::is_const<typename std::remove_reference<T1>::type>,
const T2&, const T2&, T2&>,
T2&>,
mp11::mp_if<std::is_const<T1>, const T2, T2>>>; mp11::mp_if<std::is_const<T1>, const T2, T2>>>;
template <typename S, typename L> template <typename S, typename L>

View File

@ -41,11 +41,8 @@ inline void escape(std::ostream& os, const string_view s) {
// the following is highly optimized code that runs in a hot loop; // the following is highly optimized code that runs in a hot loop;
// please measure the performance impact of changes // please measure the performance impact of changes
inline void lin(std::size_t& out, inline void lin(std::size_t& out, std::size_t& stride, const int axis_size,
std::size_t& stride, const int axis_shape, int j) noexcept {
const int axis_size,
const int axis_shape,
int j) noexcept {
BOOST_ASSERT_MSG(stride == 0 || (-1 <= j && j <= axis_size), BOOST_ASSERT_MSG(stride == 0 || (-1 <= j && j <= axis_size),
"index must be in bounds for this algorithm"); "index must be in bounds for this algorithm");
j += (j < 0) * (axis_size + 2); // wrap around if j < 0 j += (j < 0) * (axis_size + 2); // wrap around if j < 0
@ -53,7 +50,8 @@ inline void lin(std::size_t& out,
#ifndef _MSC_VER #ifndef _MSC_VER
#pragma GCC diagnostic ignored "-Wstrict-overflow" #pragma GCC diagnostic ignored "-Wstrict-overflow"
#endif #endif
stride *= (j < axis_shape) * axis_shape; // stride == 0 indicates out-of-range stride *=
(j < axis_shape) * axis_shape; // stride == 0 indicates out-of-range
} }
template <typename T> template <typename T>
@ -84,8 +82,7 @@ inline void fill_storage(S& s, std::size_t idx) {
template <typename S> template <typename S>
inline auto storage_get(const S& s, std::size_t idx, bool error) -> inline auto storage_get(const S& s, std::size_t idx, bool error) ->
typename S::const_reference { typename S::const_reference {
if (error) if (error) throw std::out_of_range("bin index out of range");
throw std::out_of_range("bin index out of range");
return s[idx]; return s[idx];
} }

View File

@ -69,8 +69,7 @@ class histogram<dynamic_tag, Axes, Storage> {
histogram& operator=(const histogram&) = default; histogram& operator=(const histogram&) = default;
histogram& operator=(histogram&&) = default; histogram& operator=(histogram&&) = default;
template <typename Axis0, template <typename Axis0, typename... Axis,
typename... Axis,
typename = detail::requires_axis<Axis0>> typename = detail::requires_axis<Axis0>>
explicit histogram(Axis0&& axis0, Axis&&... axis) explicit histogram(Axis0&& axis0, Axis&&... axis)
: axes_({any_axis_type(std::forward<Axis0>(axis0)), : axes_({any_axis_type(std::forward<Axis0>(axis0)),
@ -161,9 +160,7 @@ class histogram<dynamic_tag, Axes, Storage> {
"(did you use weight() in the wrong place?)"); "(did you use weight() in the wrong place?)");
std::size_t idx = 0, stride = 1; std::size_t idx = 0, stride = 1;
xlin<0>(idx, stride, std::forward<Ts>(ts)...); xlin<0>(idx, stride, std::forward<Ts>(ts)...);
if (stride) { if (stride) { detail::fill_storage(storage_, idx); }
detail::fill_storage(storage_, idx);
}
} }
template <typename T> template <typename T>
@ -183,9 +180,7 @@ class histogram<dynamic_tag, Axes, Storage> {
"fill arguments does not match histogram dimension"); "fill arguments does not match histogram dimension");
std::size_t idx = 0, stride = 1; std::size_t idx = 0, stride = 1;
xlin<0>(idx, stride, std::forward<Ts>(ts)...); xlin<0>(idx, stride, std::forward<Ts>(ts)...);
if (stride) { if (stride) { detail::fill_storage(storage_, idx, std::move(w)); }
detail::fill_storage(storage_, idx, std::move(w));
}
} }
template <typename W, typename T> template <typename W, typename T>
@ -260,8 +255,7 @@ class histogram<dynamic_tag, Axes, Storage> {
template <typename... Ts> template <typename... Ts>
histogram reduce_to(int n, Ts... ts) const { histogram reduce_to(int n, Ts... ts) const {
std::vector<bool> b(dim(), false); std::vector<bool> b(dim(), false);
for (const auto& i : {n, int(ts)...}) for (const auto& i : {n, int(ts)...}) b[i] = true;
b[i] = true;
return reduce_impl(b); return reduce_impl(b);
} }
@ -269,8 +263,7 @@ class histogram<dynamic_tag, Axes, Storage> {
template <typename Iterator, typename = detail::requires_iterator<Iterator>> template <typename Iterator, typename = detail::requires_iterator<Iterator>>
histogram reduce_to(Iterator begin, Iterator end) const { histogram reduce_to(Iterator begin, Iterator end) const {
std::vector<bool> b(dim(), false); std::vector<bool> b(dim(), false);
for (; begin != end; ++begin) for (; begin != end; ++begin) b[*begin] = true;
b[*begin] = true;
return reduce_impl(b); return reduce_impl(b);
} }
@ -402,9 +395,7 @@ class histogram<dynamic_tag, Axes, Storage> {
noexcept {} noexcept {}
template <int N, typename T> template <int N, typename T>
void xlin_get(mp11::mp_int<N>, void xlin_get(mp11::mp_int<N>, std::size_t& idx, std::size_t& stride,
std::size_t& idx,
std::size_t& stride,
T&& t) const { T&& t) const {
constexpr unsigned D = detail::mp_size<T>::value - N; constexpr unsigned D = detail::mp_size<T>::value - N;
apply_visitor( apply_visitor(
@ -434,7 +425,8 @@ class histogram<dynamic_tag, Axes, Storage> {
const auto a_size = a.size(); const auto a_size = a.size();
const auto a_shape = a.shape(); const auto a_shape = a.shape();
const auto j = detail::indirect_int_cast(*iter++); const auto j = detail::indirect_int_cast(*iter++);
stride *= (-1 <= j && j <= a_size); // set stride to zero, if j is invalid stride *=
(-1 <= j && j <= a_size); // set stride to zero, if j is invalid
detail::lin(idx, stride, a_size, a_shape, j); detail::lin(idx, stride, a_size, a_shape, j);
} }
} }
@ -444,9 +436,7 @@ class histogram<dynamic_tag, Axes, Storage> {
noexcept {} noexcept {}
template <long unsigned int N, typename T> template <long unsigned int N, typename T>
void lin_get(mp11::mp_size_t<N>, void lin_get(mp11::mp_size_t<N>, std::size_t& idx, std::size_t& stride,
std::size_t& idx,
std::size_t& stride,
const T& t) const noexcept { const T& t) const noexcept {
constexpr long unsigned int D = detail::mp_size<T>::value - N; constexpr long unsigned int D = detail::mp_size<T>::value - N;
const auto& a = axes_[D]; const auto& a = axes_[D];
@ -464,17 +454,14 @@ class histogram<dynamic_tag, Axes, Storage> {
auto axes_iter = axes_.begin(); auto axes_iter = axes_.begin();
auto n_iter = n.begin(); auto n_iter = n.begin();
for (const auto& bi : b) { for (const auto& bi : b) {
if (bi) if (bi) axes.emplace_back(*axes_iter);
axes.emplace_back(*axes_iter);
*n_iter = axes_iter->shape(); *n_iter = axes_iter->shape();
++axes_iter; ++axes_iter;
++n_iter; ++n_iter;
} }
histogram h(std::move(axes)); histogram h(std::move(axes));
detail::index_mapper m(n, b); detail::index_mapper m(n, b);
do { do { h.storage_.add(m.second, storage_[m.first]); } while (m.next());
h.storage_.add(m.second, storage_[m.first]);
} while (m.next());
return h; return h;
} }
@ -499,25 +486,22 @@ make_dynamic_histogram(Axis&&... axis) {
template <typename Storage, typename... Axis> template <typename Storage, typename... Axis>
dynamic_histogram< dynamic_histogram<
mp11::mp_set_push_back<axis::types, detail::rm_cv_ref<Axis>...>, mp11::mp_set_push_back<axis::types, detail::rm_cv_ref<Axis>...>, Storage>
Storage>
make_dynamic_histogram_with(Axis&&... axis) { make_dynamic_histogram_with(Axis&&... axis) {
return dynamic_histogram< return dynamic_histogram<
mp11::mp_set_push_back<axis::types, detail::rm_cv_ref<Axis>...>, Storage>( mp11::mp_set_push_back<axis::types, detail::rm_cv_ref<Axis>...>,
std::forward<Axis>(axis)...); Storage>(std::forward<Axis>(axis)...);
} }
template <typename Iterator, typename = detail::requires_iterator<Iterator>> template <typename Iterator, typename = detail::requires_iterator<Iterator>>
dynamic_histogram< dynamic_histogram<
detail::mp_set_union<axis::types, typename Iterator::value_type::types>> detail::mp_set_union<axis::types, typename Iterator::value_type::types>>
make_dynamic_histogram(Iterator begin, Iterator end) { make_dynamic_histogram(Iterator begin, Iterator end) {
return dynamic_histogram< return dynamic_histogram<detail::mp_set_union<
detail::mp_set_union<axis::types, typename Iterator::value_type::types>>( axis::types, typename Iterator::value_type::types>>(begin, end);
begin, end);
} }
template <typename Storage, template <typename Storage, typename Iterator,
typename Iterator,
typename = detail::requires_iterator<Iterator>> typename = detail::requires_iterator<Iterator>>
dynamic_histogram< dynamic_histogram<
detail::mp_set_union<axis::types, typename Iterator::value_type::types>, detail::mp_set_union<axis::types, typename Iterator::value_type::types>,

View File

@ -27,7 +27,8 @@ struct sqrt;
struct pow; struct pow;
} // namespace transform } // namespace transform
template <typename RealType = double, typename Transform = transform::identity> template <typename RealType = double,
typename Transform = transform::identity>
class regular; class regular;
template <typename RealType = double> template <typename RealType = double>
class circular; class circular;
@ -42,10 +43,8 @@ using types = mp11::mp_list<axis::regular<double, axis::transform::identity>,
axis::regular<double, axis::transform::log>, axis::regular<double, axis::transform::log>,
axis::regular<double, axis::transform::sqrt>, axis::regular<double, axis::transform::sqrt>,
axis::regular<double, axis::transform::pow>, axis::regular<double, axis::transform::pow>,
axis::circular<double>, axis::circular<double>, axis::variable<double>,
axis::variable<double>, axis::integer<int>, axis::category<int>,
axis::integer<int>,
axis::category<int>,
axis::category<std::string>>; axis::category<std::string>>;
template <typename... Ts> template <typename... Ts>

View File

@ -21,10 +21,9 @@ namespace histogram {
template <typename Histogram> template <typename Histogram>
class iterator_over class iterator_over
: public iterator_facade<iterator_over<Histogram>, : public iterator_facade<
typename Histogram::element_type, iterator_over<Histogram>, typename Histogram::element_type,
random_access_traversal_tag, random_access_traversal_tag, typename Histogram::const_reference> {
typename Histogram::const_reference> {
public: public:
iterator_over(const Histogram& h, std::size_t idx) iterator_over(const Histogram& h, std::size_t idx)
: histogram_(h), idx_(idx) {} : histogram_(h), idx_(idx) {}

View File

@ -34,7 +34,8 @@ inline std::ostream& operator<<(std::ostream& os, const histogram<Ts...>& h) {
} }
template <typename T> template <typename T>
inline std::ostream& operator<<(std::ostream& os, const weight_counter<T>& x) { inline std::ostream& operator<<(std::ostream& os,
const weight_counter<T>& x) {
os << "weight_counter(" << x.value() << ", " << x.variance() << ")"; os << "weight_counter(" << x.value() << ", " << x.variance() << ")";
return os; return os;
} }

View File

@ -41,14 +41,14 @@ struct serialize_helper {
template <typename RealType> template <typename RealType>
template <class Archive> template <class Archive>
void weight_counter<RealType>::serialize(Archive& ar, unsigned /* version */) { void weight_counter<RealType>::serialize(Archive& ar,
unsigned /* version */) {
ar& w; ar& w;
ar& w2; ar& w2;
} }
template <class Archive, typename Container> template <class Archive, typename Container>
void serialize(Archive& ar, void serialize(Archive& ar, array_storage<Container>& store,
array_storage<Container>& store,
unsigned /* version */) { unsigned /* version */) {
ar& store.array_; ar& store.array_;
} }

View File

@ -52,8 +52,7 @@ class histogram<static_tag, Axes, Storage> {
histogram& operator=(const histogram& rhs) = default; histogram& operator=(const histogram& rhs) = default;
histogram& operator=(histogram&& rhs) = default; histogram& operator=(histogram&& rhs) = default;
template <typename Axis0, template <typename Axis0, typename... Axis,
typename... Axis,
typename = detail::requires_axis<Axis0>> typename = detail::requires_axis<Axis0>>
explicit histogram(Axis0&& axis0, Axis&&... axis) explicit histogram(Axis0&& axis0, Axis&&... axis)
: axes_(std::forward<Axis0>(axis0), std::forward<Axis>(axis)...) { : axes_(std::forward<Axis0>(axis0), std::forward<Axis>(axis)...) {
@ -154,8 +153,7 @@ class histogram<static_tag, Axes, Storage> {
"fill arguments do not match histogram dimension"); "fill arguments do not match histogram dimension");
std::size_t idx = 0, stride = 1; std::size_t idx = 0, stride = 1;
xlin<0>(idx, stride, ts...); xlin<0>(idx, stride, ts...);
if (stride) if (stride) detail::fill_storage(storage_, idx);
detail::fill_storage(storage_, idx);
} }
template <typename T> template <typename T>
@ -172,8 +170,7 @@ class histogram<static_tag, Axes, Storage> {
// case with one argument is ambiguous, is specialized below // case with one argument is ambiguous, is specialized below
std::size_t idx = 0, stride = 1; std::size_t idx = 0, stride = 1;
xlin<0>(idx, stride, ts...); xlin<0>(idx, stride, ts...);
if (stride) if (stride) detail::fill_storage(storage_, idx, std::move(w));
detail::fill_storage(storage_, idx, std::move(w));
} }
// TODO: remove as obsolete // TODO: remove as obsolete
@ -253,7 +250,8 @@ class histogram<static_tag, Axes, Storage> {
auto reduce_to(mp11::mp_int<N>, Ns...) const auto reduce_to(mp11::mp_int<N>, Ns...) const
-> static_histogram<detail::selection<Axes, mp11::mp_int<N>, Ns...>, -> static_histogram<detail::selection<Axes, mp11::mp_int<N>, Ns...>,
Storage> { Storage> {
using HR = static_histogram<detail::selection<Axes, mp11::mp_int<N>, Ns...>, using HR =
static_histogram<detail::selection<Axes, mp11::mp_int<N>, Ns...>,
Storage>; Storage>;
auto hr = auto hr =
HR(detail::make_sub_tuple<axes_type, mp11::mp_int<N>, Ns...>(axes_)); HR(detail::make_sub_tuple<axes_type, mp11::mp_int<N>, Ns...>(axes_));
@ -264,7 +262,9 @@ class histogram<static_tag, Axes, Storage> {
const_iterator begin() const noexcept { return const_iterator(*this, 0); } const_iterator begin() const noexcept { return const_iterator(*this, 0); }
const_iterator end() const noexcept { return const_iterator(*this, size()); } const_iterator end() const noexcept {
return const_iterator(*this, size());
}
private: private:
axes_type axes_; axes_type axes_;
@ -350,13 +350,11 @@ class histogram<static_tag, Axes, Storage> {
} }
template <typename Iterator> template <typename Iterator>
void xlin_iter(mp11::mp_size_t<0>, std::size_t&, std::size_t&, Iterator) const void xlin_iter(mp11::mp_size_t<0>, std::size_t&, std::size_t&,
noexcept {} Iterator) const noexcept {}
template <long unsigned int N, typename Iterator> template <long unsigned int N, typename Iterator>
void xlin_iter(mp11::mp_size_t<N>, void xlin_iter(mp11::mp_size_t<N>, std::size_t& idx, std::size_t& stride,
std::size_t& idx,
std::size_t& stride,
Iterator iter) const { Iterator iter) const {
constexpr unsigned D = axes_size::value - N; constexpr unsigned D = axes_size::value - N;
const auto a_size = std::get<D>(axes_).size(); const auto a_size = std::get<D>(axes_).size();
@ -380,13 +378,11 @@ class histogram<static_tag, Axes, Storage> {
} }
template <typename Iterator> template <typename Iterator>
void lin_iter(mp11::mp_size_t<0>, std::size_t&, std::size_t&, Iterator) const void lin_iter(mp11::mp_size_t<0>, std::size_t&, std::size_t&,
noexcept {} Iterator) const noexcept {}
template <long unsigned int N, typename Iterator> template <long unsigned int N, typename Iterator>
void lin_iter(mp11::mp_size_t<N>, void lin_iter(mp11::mp_size_t<N>, std::size_t& idx, std::size_t& stride,
std::size_t& idx,
std::size_t& stride,
Iterator iter) const noexcept { Iterator iter) const noexcept {
constexpr unsigned D = axes_size::value - N; constexpr unsigned D = axes_size::value - N;
const auto a_size = std::get<D>(axes_).size(); const auto a_size = std::get<D>(axes_).size();
@ -402,9 +398,7 @@ class histogram<static_tag, Axes, Storage> {
noexcept {} noexcept {}
template <long unsigned int N, typename T> template <long unsigned int N, typename T>
void xlin_get(mp11::mp_size_t<N>, void xlin_get(mp11::mp_size_t<N>, std::size_t& idx, std::size_t& stride,
std::size_t& idx,
std::size_t& stride,
T&& t) const { T&& t) const {
constexpr unsigned D = detail::mp_size<T>::value - N; constexpr unsigned D = detail::mp_size<T>::value - N;
const auto a_size = std::get<D>(axes_).size(); const auto a_size = std::get<D>(axes_).size();
@ -419,9 +413,7 @@ class histogram<static_tag, Axes, Storage> {
noexcept {} noexcept {}
template <long unsigned int N, typename T> template <long unsigned int N, typename T>
void lin_get(mp11::mp_size_t<N>, void lin_get(mp11::mp_size_t<N>, std::size_t& idx, std::size_t& stride,
std::size_t& idx,
std::size_t& stride,
T&& t) const noexcept { T&& t) const noexcept {
constexpr unsigned D = detail::mp_size<T>::value - N; constexpr unsigned D = detail::mp_size<T>::value - N;
const auto a_size = std::get<D>(axes_).size(); const auto a_size = std::get<D>(axes_).size();
@ -437,9 +429,7 @@ class histogram<static_tag, Axes, Storage> {
detail::shape_vector_visitor v(dim()); detail::shape_vector_visitor v(dim());
for_each_axis(v); for_each_axis(v);
detail::index_mapper m(v.shapes, b); detail::index_mapper m(v.shapes, b);
do { do { h.storage_.add(m.second, storage_[m.first]); } while (m.next());
h.storage_.add(m.second, storage_[m.first]);
} while (m.next());
} }
template <typename T, typename A, typename S> template <typename T, typename A, typename S>

View File

@ -128,13 +128,9 @@ class array<void> : public array_base {
using array_base::array_base; using array_base::array_base;
}; };
using any_array = variant<array<void>, using any_array =
array<uint8_t>, variant<array<void>, array<uint8_t>, array<uint16_t>, array<uint32_t>,
array<uint16_t>, array<uint64_t>, array<mp_int>, array<wcount>>;
array<uint32_t>,
array<uint64_t>,
array<mp_int>,
array<wcount>>;
template <typename T> template <typename T>
struct next_type; struct next_type;
@ -159,8 +155,7 @@ using next = typename next_type<T>::type;
template <typename T> template <typename T>
inline bool safe_increase(T& t) { inline bool safe_increase(T& t) {
if (t == std::numeric_limits<T>::max()) if (t == std::numeric_limits<T>::max()) return false;
return false;
++t; ++t;
return true; return true;
} }
@ -176,8 +171,7 @@ inline bool safe_assign(T& t, const U& u) {
template <typename T, typename U> template <typename T, typename U>
inline bool safe_radd(T& t, const U& u) { inline bool safe_radd(T& t, const U& u) {
if (static_cast<T>(std::numeric_limits<T>::max() - t) < u) if (static_cast<T>(std::numeric_limits<T>::max() - t) < u) return false;
return false;
t += static_cast<T>(u); t += static_cast<T>(u);
return true; return true;
} }
@ -185,8 +179,7 @@ inline bool safe_radd(T& t, const U& u) {
// float rounding is a mess, the equal sign is necessary here // float rounding is a mess, the equal sign is necessary here
template <typename T> template <typename T>
inline bool safe_radd(T& t, const double u) { inline bool safe_radd(T& t, const double u) {
if ((std::numeric_limits<T>::max() - t) <= u) if ((std::numeric_limits<T>::max() - t) <= u) return false;
return false;
t += u; t += u;
return true; return true;
} }
@ -390,24 +383,22 @@ struct rmul_visitor : public static_visitor<void> {
} }
void operator()(array<void>&) const {} void operator()(array<void>&) const {}
void operator()(array<wcount>& lhs) const { void operator()(array<wcount>& lhs) const {
for (std::size_t i = 0; i != lhs.size; ++i) for (std::size_t i = 0; i != lhs.size; ++i) lhs[i] *= x;
lhs[i] *= x;
} }
}; };
struct bicmp_visitor : public static_visitor<bool> { struct bicmp_visitor : public static_visitor<bool> {
template <typename T, typename U> template <typename T, typename U>
bool operator()(const array<T>& b1, const array<U>& b2) const { bool operator()(const array<T>& b1, const array<U>& b2) const {
if (b1.size != b2.size) if (b1.size != b2.size) return false;
return false;
return std::equal(b1.begin(), b1.end(), b2.begin()); return std::equal(b1.begin(), b1.end(), b2.begin());
} }
template <typename T> template <typename T>
bool operator()(const array<T>& b1, const array<void>& b2) const { bool operator()(const array<T>& b1, const array<void>& b2) const {
if (b1.size != b2.size) if (b1.size != b2.size) return false;
return false; return std::all_of(b1.begin(), b1.end(),
return std::all_of(b1.begin(), b1.end(), [](const T& t) { return t == 0; }); [](const T& t) { return t == 0; });
} }
template <typename T> template <typename T>
@ -429,7 +420,8 @@ class adaptive_storage {
using element_type = detail::wcount; using element_type = detail::wcount;
using const_reference = element_type; using const_reference = element_type;
explicit adaptive_storage(std::size_t s) : buffer_(detail::array<void>(s)) {} explicit adaptive_storage(std::size_t s)
: buffer_(detail::array<void>(s)) {}
adaptive_storage() = default; adaptive_storage() = default;
adaptive_storage(const adaptive_storage&) = default; adaptive_storage(const adaptive_storage&) = default;
@ -450,9 +442,7 @@ class adaptive_storage {
adaptive_storage& operator=(const RHS& rhs) { adaptive_storage& operator=(const RHS& rhs) {
// no check for self-assign needed, default operator above is better match // no check for self-assign needed, default operator above is better match
const auto n = rhs.size(); const auto n = rhs.size();
if (size() != n) { if (size() != n) { buffer_ = detail::array<void>(n); }
buffer_ = detail::array<void>(n);
}
using T = typename RHS::element_type; using T = typename RHS::element_type;
for (std::size_t i = 0; i < n; ++i) { for (std::size_t i = 0; i < n; ++i) {
apply_visitor(detail::assign_visitor<T>(buffer_, i, rhs[i]), buffer_); apply_visitor(detail::assign_visitor<T>(buffer_, i, rhs[i]), buffer_);
@ -477,7 +467,8 @@ class adaptive_storage {
apply_visitor(detail::radd_visitor<double>(buffer_, i, x.value()), apply_visitor(detail::radd_visitor<double>(buffer_, i, x.value()),
buffer_); buffer_);
} else { } else {
apply_visitor(detail::radd_visitor<element_type>(buffer_, i, x), buffer_); apply_visitor(detail::radd_visitor<element_type>(buffer_, i, x),
buffer_);
} }
} }
@ -517,8 +508,8 @@ class adaptive_storage {
template <typename RHS> template <typename RHS>
adaptive_storage& operator+=(const RHS& rhs) { adaptive_storage& operator+=(const RHS& rhs) {
for (std::size_t i = 0, n = size(); i < n; ++i) for (std::size_t i = 0, n = size(); i < n; ++i)
apply_visitor( apply_visitor(detail::radd_visitor<typename RHS::element_type>(
detail::radd_visitor<typename RHS::element_type>(buffer_, i, rhs[i]), buffer_, i, rhs[i]),
buffer_); buffer_);
return *this; return *this;
} }

View File

@ -81,26 +81,25 @@ class array_storage {
array_[i] += x; array_[i] += x;
} }
const_reference operator[](std::size_t i) const noexcept { return array_[i]; } const_reference operator[](std::size_t i) const noexcept {
return array_[i];
}
template <typename U> template <typename U>
bool operator==(const array_storage<U>& rhs) const noexcept { bool operator==(const array_storage<U>& rhs) const noexcept {
if (size_ != rhs.size_) if (size_ != rhs.size_) return false;
return false;
return std::equal(array_.get(), array_.get() + size_, rhs.array_.get()); return std::equal(array_.get(), array_.get() + size_, rhs.array_.get());
} }
template <typename S> template <typename S>
array_storage& operator+=(const S& rhs) noexcept { array_storage& operator+=(const S& rhs) noexcept {
for (std::size_t i = 0; i < size_; ++i) for (std::size_t i = 0; i < size_; ++i) add(i, rhs[i]);
add(i, rhs[i]);
return *this; return *this;
} }
template <typename U> template <typename U>
array_storage& operator*=(const U& x) noexcept { array_storage& operator*=(const U& x) noexcept {
for (std::size_t i = 0; i < size_; ++i) for (std::size_t i = 0; i < size_; ++i) array_[i] *= x;
array_[i] *= x;
return *this; return *this;
} }

View File

@ -12,22 +12,16 @@
namespace boost { namespace boost {
namespace histogram { namespace histogram {
template <typename S1, template <typename S1, typename S2, typename = detail::requires_storage<S1>,
typename S2,
typename = detail::requires_storage<S1>,
typename = detail::requires_storage<S2>> typename = detail::requires_storage<S2>>
bool operator==(const S1& s1, const S2& s2) noexcept { bool operator==(const S1& s1, const S2& s2) noexcept {
if (s1.size() != s2.size()) if (s1.size() != s2.size()) return false;
return false;
for (std::size_t i = 0, n = s1.size(); i < n; ++i) for (std::size_t i = 0, n = s1.size(); i < n; ++i)
if (!(s1[i] == s2[i])) if (!(s1[i] == s2[i])) return false;
return false;
return true; return true;
} }
template <typename S1, template <typename S1, typename S2, typename = detail::requires_storage<S1>,
typename S2,
typename = detail::requires_storage<S1>,
typename = detail::requires_storage<S2>> typename = detail::requires_storage<S2>>
bool operator!=(const S1& s1, const S2& s2) noexcept { bool operator!=(const S1& s1, const S2& s2) noexcept {
return !operator==(s1, s2); return !operator==(s1, s2);

View File

@ -4,33 +4,34 @@
// (See accompanying file LICENSE_1_0.txt // (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt) // or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "utility.hpp"
#include <boost/histogram/histogram_fwd.hpp>
#include <boost/histogram/axis/types.hpp>
#include <boost/histogram/axis/any.hpp> #include <boost/histogram/axis/any.hpp>
#include <boost/histogram/axis/ostream_operators.hpp> #include <boost/histogram/axis/ostream_operators.hpp>
#include <boost/histogram/axis/types.hpp>
#include <boost/histogram/detail/utility.hpp> #include <boost/histogram/detail/utility.hpp>
#include <boost/histogram/histogram_fwd.hpp>
#include <boost/python.hpp> #include <boost/python.hpp>
#include <boost/python/def_visitor.hpp> #include <boost/python/def_visitor.hpp>
#include <boost/python/raw_function.hpp>
#include <boost/python/make_constructor.hpp> #include <boost/python/make_constructor.hpp>
#include <boost/python/raw_function.hpp>
#include <boost/python/to_python_converter.hpp> #include <boost/python/to_python_converter.hpp>
#include "utility.hpp"
#ifdef HAVE_NUMPY #ifdef HAVE_NUMPY
#include <boost/python/numpy.hpp> #include <boost/python/numpy.hpp>
namespace np = boost::python::numpy; namespace np = boost::python::numpy;
#endif #endif
#include <sstream>
#include <type_traits>
#include <vector>
#include <utility>
#include <iostream> #include <iostream>
#include <sstream>
#include <stdexcept> #include <stdexcept>
#include <type_traits>
#include <utility>
#include <vector>
namespace bp = boost::python; namespace bp = boost::python;
namespace bh = boost::histogram; namespace bh = boost::histogram;
namespace bha = boost::histogram::axis; namespace bha = boost::histogram::axis;
template <typename T> bp::str generic_repr(const T &t) { template <typename T>
bp::str generic_repr(const T& t) {
std::ostringstream os; std::ostringstream os;
os << t; os << t;
return os.str().c_str(); return os.str().c_str();
@ -56,19 +57,15 @@ generic_iterator make_generic_iterator(bp::object self) {
} }
template <typename Axis> template <typename Axis>
struct axis_value_view_to_python struct axis_value_view_to_python {
{ static PyObject* convert(const bha::value_view<Axis>& i) {
static PyObject* convert(const bha::value_view<Axis> &i)
{
return bp::incref(bp::object(i.value()).ptr()); return bp::incref(bp::object(i.value()).ptr());
} }
}; };
template <typename Axis> template <typename Axis>
struct axis_interval_view_to_python struct axis_interval_view_to_python {
{ static PyObject* convert(const bha::interval_view<Axis>& i) {
static PyObject* convert(const bha::interval_view<Axis> &i)
{
return bp::incref(bp::make_tuple(i.lower(), i.upper()).ptr()); return bp::incref(bp::make_tuple(i.lower(), i.upper()).ptr());
} }
}; };
@ -96,10 +93,8 @@ bp::object variable_init(bp::tuple args, bp::dict kwargs) {
if (k == "label") if (k == "label")
label = boost::string_view(bp::extract<const char*>(v), bp::len(v)); label = boost::string_view(bp::extract<const char*>(v), bp::len(v));
else if (k == "uoflow") { else if (k == "uoflow") {
if (!bp::extract<bool>(v)) if (!bp::extract<bool>(v)) uo = bha::uoflow::off;
uo = bha::uoflow::off; } else {
}
else {
std::stringstream s; std::stringstream s;
s << "keyword " << k << " not recognized"; s << "keyword " << k << " not recognized";
PyErr_SetString(PyExc_KeyError, s.str().c_str()); PyErr_SetString(PyExc_KeyError, s.str().c_str());
@ -142,30 +137,34 @@ bp::object category_init(bp::tuple args, bp::dict kwargs) {
return self.attr("__init__")(bha::category<>(c.begin(), c.end(), label)); return self.attr("__init__")(bha::category<>(c.begin(), c.end(), label));
} }
template <typename T> void axis_set_label(T& t, bp::str s) { template <typename T>
t.label({bp::extract<const char*>(s)(), void axis_set_label(T& t, bp::str s) {
static_cast<std::size_t>(bp::len(s))}); t.label(
{bp::extract<const char*>(s)(), static_cast<std::size_t>(bp::len(s))});
} }
template <typename T> bp::str axis_get_label(const T& t) { template <typename T>
bp::str axis_get_label(const T& t) {
auto s = t.label(); auto s = t.label();
return {s.data(), s.size()}; return {s.data(), s.size()};
} }
template <typename A> bp::object axis_getitem(const A &a, int i) { template <typename A>
bp::object axis_getitem(const A& a, int i) {
if (i < -1 * a.uoflow() || i >= a.size() + 1 * a.uoflow()) if (i < -1 * a.uoflow() || i >= a.size() + 1 * a.uoflow())
throw std::out_of_range("index out of bounds"); throw std::out_of_range("index out of bounds");
return bp::make_tuple(a.lower(i), a.lower(i + 1)); return bp::make_tuple(a.lower(i), a.lower(i + 1));
} }
template <> bp::object axis_getitem<bha::category<>>(const bha::category<> &a, int i) { template <>
if (i < 0 || i >= a.size()) bp::object axis_getitem<bha::category<>>(const bha::category<>& a, int i) {
throw std::out_of_range("index out of bounds"); if (i < 0 || i >= a.size()) throw std::out_of_range("index out of bounds");
return bp::object(a.value(i)); return bp::object(a.value(i));
} }
#ifdef HAVE_NUMPY #ifdef HAVE_NUMPY
template <typename Axis> bp::object axis_array_interface(const Axis& axis) { template <typename Axis>
bp::object axis_array_interface(const Axis& axis) {
using T = typename std::decay<typename Axis::value_type>::type; using T = typename std::decay<typename Axis::value_type>::type;
bp::dict d; bp::dict d;
auto shape = bp::make_tuple(axis.size() + 1); auto shape = bp::make_tuple(axis.size() + 1);
@ -174,14 +173,15 @@ template <typename Axis> bp::object axis_array_interface(const Axis& axis) {
// make new array, and pass it to Python // make new array, and pass it to Python
auto a = np::empty(shape, np::dtype::get_builtin<T>()); auto a = np::empty(shape, np::dtype::get_builtin<T>());
auto buf = reinterpret_cast<T*>(a.get_data()); auto buf = reinterpret_cast<T*>(a.get_data());
for (auto i = 0; i < axis.size()+1; ++i) for (auto i = 0; i < axis.size() + 1; ++i) buf[i] = axis.lower(i);
buf[i] = axis.lower(i);
d["data"] = a; d["data"] = a;
d["version"] = 3; d["version"] = 3;
return d; return d;
} }
template <> bp::object axis_array_interface<bha::category<>>(const bha::category<>& axis) { template <>
bp::object axis_array_interface<bha::category<>>(
const bha::category<>& axis) {
bp::dict d; bp::dict d;
auto shape = bp::make_tuple(axis.size()); auto shape = bp::make_tuple(axis.size());
d["shape"] = shape; d["shape"] = shape;
@ -189,8 +189,7 @@ template <> bp::object axis_array_interface<bha::category<>>(const bha::category
// make new array, and pass it to Python // make new array, and pass it to Python
auto a = np::empty(shape, np::dtype::get_builtin<int>()); auto a = np::empty(shape, np::dtype::get_builtin<int>());
auto buf = reinterpret_cast<int*>(a.get_data()); auto buf = reinterpret_cast<int*>(a.get_data());
for (auto i = 0; i < axis.size(); ++i) for (auto i = 0; i < axis.size(); ++i) buf[i] = axis.value(i);
buf[i] = axis.value(i);
d["data"] = a; d["data"] = a;
d["version"] = 3; d["version"] = 3;
return d; return d;
@ -199,14 +198,15 @@ template <> bp::object axis_array_interface<bha::category<>>(const bha::category
template <class T> template <class T>
struct axis_suite : public bp::def_visitor<axis_suite<T>> { struct axis_suite : public bp::def_visitor<axis_suite<T>> {
template <class Class> static void visit(Class &cl) { template <class Class>
cl.add_property( static void visit(Class& cl) {
"shape", &T::shape, cl.add_property("shape", &T::shape,
"Number of bins, including over-/underflow bins if they are present."); "Number of bins, including over-/underflow bins if they "
cl.add_property( "are present.");
"label", axis_get_label<T>, axis_set_label<T>, cl.add_property("label", axis_get_label<T>, axis_set_label<T>,
"Name or description for the axis."); "Name or description for the axis.");
cl.def("index", &T::index, ":param float x: value" cl.def("index", &T::index,
":param float x: value"
"\n:returns: bin index for the passed value", "\n:returns: bin index for the passed value",
bp::args("self", "x")); bp::args("self", "x"));
cl.def("__len__", &T::size, cl.def("__len__", &T::size,
@ -227,33 +227,29 @@ struct axis_suite : public bp::def_visitor<axis_suite<T>> {
}; };
template <typename Transform> template <typename Transform>
bha::regular<double, Transform>* regular_init( bha::regular<double, Transform>* regular_init(unsigned bin, double lower,
unsigned bin, double lower, double upper, double upper, bp::str pylabel,
bp::str pylabel, bool with_uoflow) bool with_uoflow) {
{
const auto uo = with_uoflow ? bha::uoflow::on : bha::uoflow::off; const auto uo = with_uoflow ? bha::uoflow::on : bha::uoflow::off;
return new bha::regular<double, Transform>(bin, lower, upper, return new bha::regular<double, Transform>(
{bp::extract<const char*>(pylabel)(), bin, lower, upper, {bp::extract<const char*>(pylabel)(),
static_cast<std::size_t>(bp::len(pylabel))}, static_cast<std::size_t>(bp::len(pylabel))},
uo); uo);
} }
bha::regular<double, bha::transform::pow>* regular_pow_init( bha::regular<double, bha::transform::pow>* regular_pow_init(
unsigned bin, double lower, double upper, double power, unsigned bin, double lower, double upper, double power, bp::str pylabel,
bp::str pylabel, bool with_uoflow) bool with_uoflow) {
{
using namespace ::boost::python; using namespace ::boost::python;
const auto uo = with_uoflow ? bha::uoflow::on : bha::uoflow::off; const auto uo = with_uoflow ? bha::uoflow::on : bha::uoflow::off;
return new bha::regular<double, bha::transform::pow>( return new bha::regular<double, bha::transform::pow>(
bin, lower, upper, bin, lower, upper, {extract<const char*>(pylabel)(),
{extract<const char*>(pylabel)(),
static_cast<std::size_t>(bp::len(pylabel))}, static_cast<std::size_t>(bp::len(pylabel))},
uo, power); uo, power);
} }
bha::integer<>* integer_init(int lower, int upper, bha::integer<>* integer_init(int lower, int upper, bp::str pylabel,
bp::str pylabel, bool with_uoflow) bool with_uoflow) {
{
using namespace ::boost::python; using namespace ::boost::python;
const auto uo = with_uoflow ? bha::uoflow::on : bha::uoflow::off; const auto uo = with_uoflow ? bha::uoflow::on : bha::uoflow::off;
return new bha::integer<>(lower, upper, return new bha::integer<>(lower, upper,
@ -273,12 +269,12 @@ void register_axis_types() {
.def("next", &generic_iterator::next) // Python2 .def("next", &generic_iterator::next) // Python2
; ;
class_<bha::regular<>>( class_<bha::regular<>>("regular",
"regular",
"Axis for real-valued data and bins of equal width." "Axis for real-valued data and bins of equal width."
"\nBinning is a O(1) operation.", "\nBinning is a O(1) operation.",
no_init) no_init)
.def("__init__", make_constructor(regular_init<bha::transform::identity>, .def("__init__",
make_constructor(regular_init<bha::transform::identity>,
default_call_policies(), default_call_policies(),
(arg("bin"), arg("lower"), arg("upper"), (arg("bin"), arg("lower"), arg("upper"),
arg("label") = "", arg("uoflow") = true))) arg("label") = "", arg("uoflow") = true)))
@ -287,10 +283,12 @@ void register_axis_types() {
#define BOOST_HISTOGRAM_PYTHON_REGULAR_CLASS(x) \ #define BOOST_HISTOGRAM_PYTHON_REGULAR_CLASS(x) \
class_<bha::regular<double, bha::transform::x>>( \ class_<bha::regular<double, bha::transform::x>>( \
"regular_" #x, \ "regular_" #x, \
"Axis for real-valued data and bins of equal width in "#x"-space." \ "Axis for real-valued data and bins of equal width in " #x \
"-space." \
"\nBinning is a O(1) operation.", \ "\nBinning is a O(1) operation.", \
no_init) \ no_init) \
.def("__init__", make_constructor(regular_init<bha::transform::x>, \ .def("__init__", \
make_constructor(regular_init<bha::transform::x>, \
default_call_policies(), \ default_call_policies(), \
(arg("bin"), arg("lower"), arg("upper"), \ (arg("bin"), arg("lower"), arg("upper"), \
arg("label") = "", arg("uoflow") = true))) \ arg("label") = "", arg("uoflow") = true))) \
@ -305,8 +303,9 @@ void register_axis_types() {
"Axis for real-valued data and bins of equal width in power-space." "Axis for real-valued data and bins of equal width in power-space."
"\nBinning is a O(1) operation.", "\nBinning is a O(1) operation.",
no_init) no_init)
.def("__init__", make_constructor(regular_pow_init, .def("__init__",
default_call_policies(), make_constructor(
regular_pow_init, default_call_policies(),
(arg("bin"), arg("lower"), arg("upper"), arg("power"), (arg("bin"), arg("lower"), arg("upper"), arg("power"),
arg("label") = "", arg("uoflow") = true))) arg("label") = "", arg("uoflow") = true)))
.def(axis_suite<bha::regular<double, bha::transform::pow>>()); .def(axis_suite<bha::regular<double, bha::transform::pow>>());
@ -320,8 +319,7 @@ void register_axis_types() {
no_init) no_init)
.def(init<unsigned, double, double, const char*>( .def(init<unsigned, double, double, const char*>(
(arg("self"), arg("bin"), arg("phase") = 0.0, (arg("self"), arg("bin"), arg("phase") = 0.0,
arg("perimeter") = bh::detail::two_pi, arg("perimeter") = bh::detail::two_pi, arg("label") = "")))
arg("label") = "")))
.def(axis_suite<bha::circular<>>()); .def(axis_suite<bha::circular<>>());
class_<bha::variable<>>( class_<bha::variable<>>(
@ -340,8 +338,8 @@ void register_axis_types() {
"\nthat are one integer wide. Faster than a regular axis." "\nthat are one integer wide. Faster than a regular axis."
"\nBinning is a O(1) operation.", "\nBinning is a O(1) operation.",
no_init) no_init)
.def("__init__", make_constructor(integer_init, .def("__init__",
default_call_policies(), make_constructor(integer_init, default_call_policies(),
(arg("lower"), arg("upper"), arg("label") = "", (arg("lower"), arg("upper"), arg("label") = "",
arg("uoflow") = true))) arg("uoflow") = true)))
.def(axis_suite<bha::integer<>>()); .def(axis_suite<bha::integer<>>());

View File

@ -4,18 +4,18 @@
// (See accompanying file LICENSE_1_0.txt // (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt) // or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "serialization_suite.hpp" #include <boost/histogram/detail/cat.hpp>
#include "utility.hpp"
#include <boost/histogram/dynamic_histogram.hpp> #include <boost/histogram/dynamic_histogram.hpp>
#include <boost/histogram/storage/adaptive_storage.hpp>
#include <boost/histogram/ostream_operators.hpp> #include <boost/histogram/ostream_operators.hpp>
#include <boost/histogram/serialization.hpp> #include <boost/histogram/serialization.hpp>
#include <boost/histogram/detail/cat.hpp> #include <boost/histogram/storage/adaptive_storage.hpp>
#include <boost/python.hpp> #include <boost/python.hpp>
#include <boost/python/raw_function.hpp> #include <boost/python/raw_function.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/variant/apply_visitor.hpp> #include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp> #include <boost/variant/static_visitor.hpp>
#include "serialization_suite.hpp"
#include "utility.hpp"
#ifdef HAVE_NUMPY #ifdef HAVE_NUMPY
#include <boost/python/numpy.hpp> #include <boost/python/numpy.hpp>
namespace np = boost::python::numpy; namespace np = boost::python::numpy;
@ -85,10 +85,10 @@ public:
// double array, fill it and pass it // double array, fill it and pass it
auto a = np::empty(tuple(shapes), np::dtype::get_builtin<double>()); auto a = np::empty(tuple(shapes), np::dtype::get_builtin<double>());
for (auto i = 0l, n = bp::len(shapes); i < n; ++i) for (auto i = 0l, n = bp::len(shapes); i < n; ++i)
const_cast<Py_intptr_t*>(a.get_strides())[i] = bp::extract<int>(strides[i]); const_cast<Py_intptr_t*>(a.get_strides())[i] =
bp::extract<int>(strides[i]);
auto* buf = (double*)a.get_data(); auto* buf = (double*)a.get_data();
for (auto i = 0ul; i < b.size; ++i) for (auto i = 0ul; i < b.size; ++i) buf[i] = static_cast<double>(b[i]);
buf[i] = static_cast<double>(b[i]);
return a; return a;
} }
}; };
@ -103,8 +103,7 @@ public:
if (i) strides.append(strides[-1] * shapes[-1]); if (i) strides.append(strides[-1] * shapes[-1]);
shapes.append(self.axis(i).shape()); shapes.append(self.axis(i).shape());
} }
if (self.dim() == 0) if (self.dim() == 0) shapes.append(0);
shapes.append(0);
d["shape"] = tuple(shapes); d["shape"] = tuple(shapes);
d["strides"] = tuple(strides); d["strides"] = tuple(strides);
d["data"] = boost::apply_visitor(data_visitor(shapes, strides), b); d["data"] = boost::apply_visitor(data_visitor(shapes, strides), b);
@ -117,7 +116,8 @@ public:
} // namespace boost } // namespace boost
struct axis_visitor : public boost::static_visitor<bp::object> { struct axis_visitor : public boost::static_visitor<bp::object> {
template <typename T> bp::object operator()(const T &t) const { template <typename T>
bp::object operator()(const T& t) const {
return bp::object(t); return bp::object(t);
} }
}; };
@ -126,9 +126,10 @@ struct axes_appender {
bp::object obj; bp::object obj;
pyhistogram::axes_type& axes; pyhistogram::axes_type& axes;
bool& success; bool& success;
axes_appender(bp::object o, pyhistogram::axes_type& a, axes_appender(bp::object o, pyhistogram::axes_type& a, bool& s)
bool& s) : obj(o), axes(a), success(s) {} : obj(o), axes(a), success(s) {}
template <typename A> void operator()(const A&) const { template <typename A>
void operator()(const A&) const {
if (success) return; if (success) return;
bp::extract<const A&> get_axis(obj); bp::extract<const A&> get_axis(obj);
if (get_axis.check()) { if (get_axis.check()) {
@ -139,8 +140,7 @@ struct axes_appender {
}; };
bp::object histogram_axis(const pyhistogram& self, int i) { bp::object histogram_axis(const pyhistogram& self, int i) {
if (i < 0) if (i < 0) i += self.dim();
i += self.dim();
if (i < 0 || i >= int(self.dim())) if (i < 0 || i >= int(self.dim()))
throw std::out_of_range("axis index out of range"); throw std::out_of_range("axis index out of range");
return boost::apply_visitor(axis_visitor(), self.axis(i)); return boost::apply_visitor(axis_visitor(), self.axis(i));
@ -163,8 +163,7 @@ bp::object histogram_init(bp::tuple args, bp::dict kwargs) {
bp::object pa = args[i + 1]; bp::object pa = args[i + 1];
bool success = false; bool success = false;
boost::mp11::mp_for_each<pyhistogram::any_axis_type::types>( boost::mp11::mp_for_each<pyhistogram::any_axis_type::types>(
axes_appender(pa, axes, success) axes_appender(pa, axes, success));
);
if (!success) { if (!success) {
std::string msg = "require an axis object, got "; std::string msg = "require an axis object, got ";
msg += bp::extract<std::string>(pa.attr("__class__"))(); msg += bp::extract<std::string>(pa.attr("__class__"))();
@ -204,8 +203,7 @@ struct fetcher {
} }
const T& operator[](long i) const noexcept { const T& operator[](long i) const noexcept {
if (n > 0) if (n > 0) return carray[i];
return carray[i];
return value; return value;
} }
}; };
@ -224,14 +222,16 @@ bp::object histogram_fill(bp::tuple args, bp::dict kwargs) {
const unsigned dim = nargs - 1; const unsigned dim = nargs - 1;
if (dim != self.dim()) { if (dim != self.dim()) {
PyErr_SetString(PyExc_ValueError, "number of arguments and dimension do not match"); PyErr_SetString(PyExc_ValueError,
"number of arguments and dimension do not match");
bp::throw_error_already_set(); bp::throw_error_already_set();
} }
if (dim > BOOST_HISTOGRAM_AXIS_LIMIT) { if (dim > BOOST_HISTOGRAM_AXIS_LIMIT) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
bh::detail::cat("too many arguments, maximum is ", bh::detail::cat("too many arguments, maximum is ",
BOOST_HISTOGRAM_AXIS_LIMIT).c_str()); BOOST_HISTOGRAM_AXIS_LIMIT)
.c_str());
bp::throw_error_already_set(); bp::throw_error_already_set();
} }
@ -241,7 +241,8 @@ bp::object histogram_fill(bp::tuple args, bp::dict kwargs) {
fetch[d].assign(args[1 + d]); fetch[d].assign(args[1 + d]);
if (fetch[d].n > 0) { if (fetch[d].n > 0) {
if (n > 0 && fetch[d].n != n) { if (n > 0 && fetch[d].n != n) {
PyErr_SetString(PyExc_ValueError, "lengths of sequences do not match"); PyErr_SetString(PyExc_ValueError,
"lengths of sequences do not match");
bp::throw_error_already_set(); bp::throw_error_already_set();
} }
n = fetch[d].n; n = fetch[d].n;
@ -261,7 +262,8 @@ bp::object histogram_fill(bp::tuple args, bp::dict kwargs) {
fetch_weight.assign(kwargs.get("weight")); fetch_weight.assign(kwargs.get("weight"));
if (fetch_weight.n > 0) { if (fetch_weight.n > 0) {
if (n > 0 && fetch_weight.n != n) { if (n > 0 && fetch_weight.n != n) {
PyErr_SetString(PyExc_ValueError, "length of weight sequence does not match"); PyErr_SetString(PyExc_ValueError,
"length of weight sequence does not match");
bp::throw_error_already_set(); bp::throw_error_already_set();
} }
n = fetch_weight.n; n = fetch_weight.n;
@ -275,22 +277,18 @@ bp::object histogram_fill(bp::tuple args, bp::dict kwargs) {
for (auto i = 0l; i < n; ++i) for (auto i = 0l; i < n; ++i)
self(bh::weight(fetch_weight[i]), fetch[0][i]); self(bh::weight(fetch_weight[i]), fetch[0][i]);
} else { } else {
for (auto i = 0l; i < n; ++i) for (auto i = 0l; i < n; ++i) self(fetch[0][i]);
self(fetch[0][i]);
} }
} else { } else {
double v[BOOST_HISTOGRAM_AXIS_LIMIT]; double v[BOOST_HISTOGRAM_AXIS_LIMIT];
if (fetch_weight.n >= 0) { if (fetch_weight.n >= 0) {
for (auto i = 0l; i < n; ++i) { for (auto i = 0l; i < n; ++i) {
for (auto d = 0u; d < dim; ++d) for (auto d = 0u; d < dim; ++d) v[d] = fetch[d][i];
v[d] = fetch[d][i];
self(bh::weight(fetch_weight[i]), span<double>{v, dim}); self(bh::weight(fetch_weight[i]), span<double>{v, dim});
} }
} } else {
else {
for (auto i = 0l; i < n; ++i) { for (auto i = 0l; i < n; ++i) {
for (auto d = 0u; d < dim; ++d) for (auto d = 0u; d < dim; ++d) v[d] = fetch[d][i];
v[d] = fetch[d][i];
self(span<double>{v, dim}); self(span<double>{v, dim});
} }
} }
@ -319,13 +317,13 @@ bp::object histogram_getitem(const pyhistogram& self, bp::object args) {
if (dim > BOOST_HISTOGRAM_AXIS_LIMIT) { if (dim > BOOST_HISTOGRAM_AXIS_LIMIT) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
bh::detail::cat("too many arguments, maximum is ", bh::detail::cat("too many arguments, maximum is ",
BOOST_HISTOGRAM_AXIS_LIMIT).c_str()); BOOST_HISTOGRAM_AXIS_LIMIT)
.c_str());
bp::throw_error_already_set(); bp::throw_error_already_set();
} }
int idx[BOOST_HISTOGRAM_AXIS_LIMIT]; int idx[BOOST_HISTOGRAM_AXIS_LIMIT];
for (unsigned i = 0; i < dim; ++i) for (unsigned i = 0; i < dim; ++i) idx[i] = bp::extract<int>(args[i]);
idx[i] = bp::extract<int>(args[i]);
return bp::object(self.at(span<int>{idx, self.dim()})); return bp::object(self.at(span<int>{idx, self.dim()}));
} }
@ -350,7 +348,8 @@ bp::object histogram_reduce_to(bp::tuple args, bp::dict kwargs) {
if (nargs > BOOST_HISTOGRAM_AXIS_LIMIT) { if (nargs > BOOST_HISTOGRAM_AXIS_LIMIT) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
bh::detail::cat("too many arguments, maximum is ", bh::detail::cat("too many arguments, maximum is ",
BOOST_HISTOGRAM_AXIS_LIMIT).c_str()); BOOST_HISTOGRAM_AXIS_LIMIT)
.c_str());
bp::throw_error_already_set(); bp::throw_error_already_set();
} }
@ -360,8 +359,7 @@ bp::object histogram_reduce_to(bp::tuple args, bp::dict kwargs) {
} }
int idx[BOOST_HISTOGRAM_AXIS_LIMIT]; int idx[BOOST_HISTOGRAM_AXIS_LIMIT];
for (auto i = 0u; i < nargs; ++i) for (auto i = 0u; i < nargs; ++i) idx[i] = bp::extract<int>(args[1 + i]);
idx[i] = bp::extract<int>(args[1 + i]);
return bp::object(self.reduce_to(idx, idx + nargs)); return bp::object(self.reduce_to(idx, idx + nargs));
} }
@ -370,31 +368,31 @@ std::string histogram_repr(const pyhistogram &h) {
return bh::detail::cat(h); return bh::detail::cat(h);
} }
double element_value(const pyhistogram::element_type& b) { double element_value(const pyhistogram::element_type& b) { return b.value(); }
return b.value();
}
double element_variance(const pyhistogram::element_type& b) { double element_variance(const pyhistogram::element_type& b) {
return b.variance(); return b.variance();
} }
double element_getitem(const pyhistogram::element_type& e, int i) { double element_getitem(const pyhistogram::element_type& e, int i) {
if (i < 0 || i > 1) if (i < 0 || i > 1) throw std::out_of_range("element_getitem");
throw std::out_of_range("element_getitem");
return i == 0 ? e.value() : e.variance(); return i == 0 ? e.value() : e.variance();
} }
int element_len(const pyhistogram::element_type&) { return 2; } int element_len(const pyhistogram::element_type&) { return 2; }
std::string element_repr(const pyhistogram::element_type& e) { std::string element_repr(const pyhistogram::element_type& e) {
return bh::detail::cat("histogram.element(", e.value(), ", ", e.variance(), ")"); return bh::detail::cat("histogram.element(", e.value(), ", ", e.variance(),
")");
} }
void register_histogram() { void register_histogram() {
bp::docstring_options dopt(true, true, false); bp::docstring_options dopt(true, true, false);
bp::scope s = bp::class_<pyhistogram, boost::shared_ptr<pyhistogram>>( bp::scope s =
"histogram", "N-dimensional histogram for real-valued data.", bp::no_init) bp::class_<pyhistogram, boost::shared_ptr<pyhistogram>>(
"histogram", "N-dimensional histogram for real-valued data.",
bp::no_init)
.def("__init__", bp::raw_function(histogram_init), .def("__init__", bp::raw_function(histogram_init),
":param axis args: axis objects" ":param axis args: axis objects"
"\nPass one or more axis objects to configure the histogram.") "\nPass one or more axis objects to configure the histogram.")
@ -408,20 +406,24 @@ void register_histogram() {
.def("axis", histogram_axis, bp::arg("i") = 0, .def("axis", histogram_axis, bp::arg("i") = 0,
":param int i: axis index" ":param int i: axis index"
"\n:return: corresponding axis object") "\n:return: corresponding axis object")
.def("__call__", bp::raw_function(histogram_fill), .def(
"__call__", bp::raw_function(histogram_fill),
":param double args: values (number must match dimension)" ":param double args: values (number must match dimension)"
"\n:keyword double weight: optional weight" "\n:keyword double weight: optional weight"
"\n" "\n"
"\nIf Numpy support is enabled, 1d-arrays can be passed instead of" "\nIf Numpy support is enabled, 1d-arrays can be passed "
"instead of"
"\nvalues, which must be equal in lenght. Arrays and values can" "\nvalues, which must be equal in lenght. Arrays and values can"
"\nbe mixed arbitrarily in the same call.") "\nbe mixed arbitrarily in the same call.")
.def("__len__", &pyhistogram::size, .def("__len__", &pyhistogram::size,
":return: total number of bins, including under- and overflow") ":return: total number of bins, including under- and overflow")
.def("at", bp::raw_function(histogram_at), .def("at", bp::raw_function(histogram_at),
":param int args: indices of the bin (number must match dimension)" ":param int args: indices of the bin (number must match "
"dimension)"
"\n:return: bin content") "\n:return: bin content")
.def("__getitem__", histogram_getitem, .def("__getitem__", histogram_getitem,
":param int args: indices of the bin (number must match dimension)" ":param int args: indices of the bin (number must match "
"dimension)"
"\n:return: bin content") "\n:return: bin content")
.def("reduce_to", bp::raw_function(histogram_reduce_to), .def("reduce_to", bp::raw_function(histogram_reduce_to),
":param int args: indices of the axes in the reduced histogram" ":param int args: indices of the axes in the reduced histogram"
@ -436,8 +438,7 @@ void register_histogram() {
.def(bp::self * double()) .def(bp::self * double())
.def(double() * bp::self) .def(double() * bp::self)
.def(bp::self + bp::self) .def(bp::self + bp::self)
.def_pickle(bh::serialization_suite<pyhistogram>()) .def_pickle(bh::serialization_suite<pyhistogram>());
;
bp::class_<pyhistogram::element_type>( bp::class_<pyhistogram::element_type>(
"element", "Holds value and variance of bin count.", "element", "Holds value and variance of bin count.",
@ -453,6 +454,5 @@ void register_histogram() {
.def(bp::self + bp::self) .def(bp::self + bp::self)
.def(bp::self + double()) .def(bp::self + double())
.def(double() + bp::self) .def(double() + bp::self)
.def("__repr__", element_repr) .def("__repr__", element_repr);
;
} }

View File

@ -5,8 +5,8 @@
// or copy at http://www.boost.org/LICENSE_1_0.txt) // or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/module.hpp> #include <boost/python/module.hpp>
#include <boost/python/scope.hpp>
#include <boost/python/object.hpp> #include <boost/python/object.hpp>
#include <boost/python/scope.hpp>
#ifdef HAVE_NUMPY #ifdef HAVE_NUMPY
#include <boost/python/numpy.hpp> #include <boost/python/numpy.hpp>
#endif #endif
@ -23,9 +23,7 @@ BOOST_PYTHON_MODULE(histogram) {
#else #else
current.attr("HAVE_NUMPY") = false; current.attr("HAVE_NUMPY") = false;
#endif #endif
object axis_module = object( object axis_module = object(borrowed(PyImport_AddModule("histogram.axis")));
borrowed(PyImport_AddModule("histogram.axis"))
);
current.attr("axis") = axis_module; current.attr("axis") = axis_module;
{ {
scope current = axis_module; scope current = axis_module;

View File

@ -60,7 +60,8 @@ private:
}; };
} // namespace detail } // namespace detail
template <class T> struct serialization_suite : python::pickle_suite { template <class T>
struct serialization_suite : python::pickle_suite {
static python::tuple getstate(python::object obj) { static python::tuple getstate(python::object obj) {
PyObject* pobj = 0; PyObject* pobj = 0;
iostreams::stream<detail::python_bytes_sink> os(&pobj); iostreams::stream<detail::python_bytes_sink> os(&pobj);

View File

@ -8,8 +8,8 @@
#define _BOOST_HISTOGRAM_PYTHON_UTILITY_HPP_ #define _BOOST_HISTOGRAM_PYTHON_UTILITY_HPP_
#include <boost/python/str.hpp> #include <boost/python/str.hpp>
#include <type_traits>
#include <stdexcept> #include <stdexcept>
#include <type_traits>
namespace boost { namespace boost {
namespace python { namespace python {

View File

@ -190,8 +190,7 @@ void convert_array_storage_impl() {
array_storage<float> t(std::size_t(1)); array_storage<float> t(std::size_t(1));
t.increase(0); t.increase(0);
while (t[0] < 1e20) while (t[0] < 1e20) t.add(0, t[0]);
t.add(0, t[0]);
auto d = aref; auto d = aref;
d = t; d = t;
BOOST_TEST(d == t); BOOST_TEST(d == t);

View File

@ -51,7 +51,8 @@ int main() {
{ {
axis::regular<> a{4, -2, 2}; axis::regular<> a{4, -2, 2};
BOOST_TEST_EQ(a[-1].lower(), -std::numeric_limits<double>::infinity()); BOOST_TEST_EQ(a[-1].lower(), -std::numeric_limits<double>::infinity());
BOOST_TEST_EQ(a[a.size()].upper(), std::numeric_limits<double>::infinity()); BOOST_TEST_EQ(a[a.size()].upper(),
std::numeric_limits<double>::infinity());
axis::regular<> b; axis::regular<> b;
BOOST_TEST_NOT(a == b); BOOST_TEST_NOT(a == b);
b = a; b = a;
@ -149,7 +150,8 @@ int main() {
{ {
axis::variable<> a{-1, 0, 1}; axis::variable<> a{-1, 0, 1};
BOOST_TEST_EQ(a[-1].lower(), -std::numeric_limits<double>::infinity()); BOOST_TEST_EQ(a[-1].lower(), -std::numeric_limits<double>::infinity());
BOOST_TEST_EQ(a[a.size()].upper(), std::numeric_limits<double>::infinity()); BOOST_TEST_EQ(a[a.size()].upper(),
std::numeric_limits<double>::infinity());
axis::variable<> b; axis::variable<> b;
BOOST_TEST_NOT(a == b); BOOST_TEST_NOT(a == b);
b = a; b = a;
@ -258,7 +260,8 @@ int main() {
a6 = a1; a6 = a1;
BOOST_TEST_EQ(a6, a1); BOOST_TEST_EQ(a6, a1);
axis::any<axis::regular<>, axis::integer<>> a7(axis::integer<>(0, 2)); axis::any<axis::regular<>, axis::integer<>> a7(axis::integer<>(0, 2));
BOOST_TEST_THROWS(axis::any<axis::regular<>> a8(a7), std::invalid_argument); BOOST_TEST_THROWS(axis::any<axis::regular<>> a8(a7),
std::invalid_argument);
BOOST_TEST_THROWS(a4 = a7, std::invalid_argument); BOOST_TEST_THROWS(a4 = a7, std::invalid_argument);
} }
@ -288,14 +291,13 @@ int main() {
axes.push_back(axis::regular<double, axis::transform::pow>( axes.push_back(axis::regular<double, axis::transform::pow>(
2, 1, 10, "regular4", axis::uoflow::off, -0.5)); 2, 1, 10, "regular4", axis::uoflow::off, -0.5));
axes.push_back(axis::circular<>(4, 0.1, 1.0, "polar")); axes.push_back(axis::circular<>(4, 0.1, 1.0, "polar"));
axes.push_back(axis::variable<>({-1, 0, 1}, "variable", axis::uoflow::off)); axes.push_back(
axis::variable<>({-1, 0, 1}, "variable", axis::uoflow::off));
axes.push_back(axis::category<>({A, B, C}, "category")); axes.push_back(axis::category<>({A, B, C}, "category"));
axes.push_back(axis::category<std::string>({a, b}, "category2")); axes.push_back(axis::category<std::string>({a, b}, "category2"));
axes.push_back(axis::integer<>(-1, 1, "integer", axis::uoflow::off)); axes.push_back(axis::integer<>(-1, 1, "integer", axis::uoflow::off));
std::ostringstream os; std::ostringstream os;
for (const auto& a : axes) { for (const auto& a : axes) { os << a << "\n"; }
os << a << "\n";
}
const std::string ref = const std::string ref =
"regular(2, -1, 1, label='regular1')\n" "regular(2, -1, 1, label='regular1')\n"
"regular_log(2, 1, 10, label='regular2', uoflow=False)\n" "regular_log(2, 1, 10, label='regular2', uoflow=False)\n"
@ -343,7 +345,8 @@ int main() {
std_vector1 = {axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1}, std_vector1 = {axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1},
axis::category<>{A, B, C}}; axis::category<>{A, B, C}};
std::vector<axis::any<axis::regular<>, axis::variable<>, axis::category<>>> std::vector<
axis::any<axis::regular<>, axis::variable<>, axis::category<>>>
std_vector2 = {axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1}, std_vector2 = {axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1},
axis::category<>{{A, B, C}}}; axis::category<>{{A, B, C}}};
@ -365,8 +368,8 @@ int main() {
std::make_tuple(axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1}, std::make_tuple(axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1},
axis::category<>{{A, B}}); axis::category<>{{A, B}});
auto tuple3 = auto tuple3 = std::make_tuple(axis::regular<>{2, -1, 1},
std::make_tuple(axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1}); axis::variable<>{-1, 0, 1});
BOOST_TEST(detail::axes_equal(std_vector1, tuple1)); BOOST_TEST(detail::axes_equal(std_vector1, tuple1));
BOOST_TEST(detail::axes_equal(tuple1, std_vector1)); BOOST_TEST(detail::axes_equal(tuple1, std_vector1));
@ -383,7 +386,8 @@ int main() {
std_vector1 = {axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1}, std_vector1 = {axis::regular<>{2, -1, 1}, axis::variable<>{-1, 0, 1},
axis::category<>{A, B, C}}; axis::category<>{A, B, C}};
std::vector<axis::any<axis::regular<>, axis::variable<>, axis::category<>>> std::vector<
axis::any<axis::regular<>, axis::variable<>, axis::category<>>>
std_vector2 = {axis::regular<>{2, -2, 2}, axis::variable<>{-2, 0, 2}, std_vector2 = {axis::regular<>{2, -2, 2}, axis::variable<>{-2, 0, 2},
axis::category<>{A, B}}; axis::category<>{A, B}};

View File

@ -3,6 +3,7 @@
using namespace boost::histogram; using namespace boost::histogram;
int main() { int main() {
auto h = make_dynamic_histogram(axis::integer<>(0, 2), axis::integer<>(0, 2)); auto h =
make_dynamic_histogram(axis::integer<>(0, 2), axis::integer<>(0, 2));
h.at(std::make_pair(-2, 0)); h.at(std::make_pair(-2, 0));
} }

View File

@ -3,6 +3,7 @@
using namespace boost::histogram; using namespace boost::histogram;
int main() { int main() {
auto h = make_dynamic_histogram(axis::integer<>(0, 2), axis::integer<>(0, 2)); auto h =
make_dynamic_histogram(axis::integer<>(0, 2), axis::integer<>(0, 2));
h.at(std::vector<int>({-2, 0})); h.at(std::vector<int>({-2, 0}));
} }

View File

@ -3,6 +3,7 @@
using namespace boost::histogram; using namespace boost::histogram;
int main() { int main() {
auto h = make_static_histogram(axis::integer<>(0, 2), axis::integer<>(0, 2)); auto h =
make_static_histogram(axis::integer<>(0, 2), axis::integer<>(0, 2));
h.at(std::vector<int>(-2, 0)); h.at(std::vector<int>(-2, 0));
} }

View File

@ -76,8 +76,8 @@ void run_tests() {
// init_2 // init_2
{ {
auto h = make_histogram<adaptive_storage>(Type(), axis::regular<>{3, -1, 1}, auto h = make_histogram<adaptive_storage>(
axis::integer<>{-1, 2}); Type(), axis::regular<>{3, -1, 1}, axis::integer<>{-1, 2});
BOOST_TEST_EQ(h.dim(), 2); BOOST_TEST_EQ(h.dim(), 2);
BOOST_TEST_EQ(h.size(), 25); BOOST_TEST_EQ(h.size(), 25);
BOOST_TEST_EQ(h.axis(0_c).shape(), 5); BOOST_TEST_EQ(h.axis(0_c).shape(), 5);
@ -89,8 +89,8 @@ void run_tests() {
// init_3 // init_3
{ {
auto h = make_histogram<adaptive_storage>(Type(), axis::regular<>{3, -1, 1}, auto h = make_histogram<adaptive_storage>(
axis::integer<>{-1, 2}, Type(), axis::regular<>{3, -1, 1}, axis::integer<>{-1, 2},
axis::circular<>{3}); axis::circular<>{3});
BOOST_TEST_EQ(h.dim(), 3); BOOST_TEST_EQ(h.dim(), 3);
BOOST_TEST_EQ(h.size(), 75); BOOST_TEST_EQ(h.size(), 75);
@ -136,7 +136,8 @@ void run_tests() {
h(0, 0); h(0, 0);
auto h2 = decltype(h)(h); auto h2 = decltype(h)(h);
BOOST_TEST(h2 == h); BOOST_TEST(h2 == h);
auto h3 = static_histogram<mp11::mp_list<axis::integer<>, axis::integer<>>, auto h3 =
static_histogram<mp11::mp_list<axis::integer<>, axis::integer<>>,
array_storage<unsigned>>(h); array_storage<unsigned>>(h);
BOOST_TEST_EQ(h3, h); BOOST_TEST_EQ(h3, h);
} }
@ -153,7 +154,8 @@ void run_tests() {
// test self-assign // test self-assign
h2 = h2; h2 = h2;
BOOST_TEST_EQ(h, h2); BOOST_TEST_EQ(h, h2);
auto h3 = static_histogram<mp11::mp_list<axis::integer<>, axis::integer<>>, auto h3 =
static_histogram<mp11::mp_list<axis::integer<>, axis::integer<>>,
array_storage<unsigned>>(); array_storage<unsigned>>();
h3 = h; h3 = h;
BOOST_TEST_EQ(h, h3); BOOST_TEST_EQ(h, h3);
@ -183,8 +185,8 @@ void run_tests() {
// axis methods // axis methods
{ {
enum { A = 3, B = 5 }; enum { A = 3, B = 5 };
auto a = make_histogram<adaptive_storage>(Type(), auto a = make_histogram<adaptive_storage>(
axis::regular<>(1, 1, 2, "foo")); Type(), axis::regular<>(1, 1, 2, "foo"));
BOOST_TEST_EQ(a.axis().size(), 1); BOOST_TEST_EQ(a.axis().size(), 1);
BOOST_TEST_EQ(a.axis().shape(), 3); BOOST_TEST_EQ(a.axis().shape(), 3);
BOOST_TEST_EQ(a.axis().index(1), 0); BOOST_TEST_EQ(a.axis().index(1), 0);
@ -203,7 +205,8 @@ void run_tests() {
b.axis().label("foo"); b.axis().label("foo");
BOOST_TEST_EQ(b.axis().label(), "foo"); BOOST_TEST_EQ(b.axis().label(), "foo");
auto c = make_histogram<adaptive_storage>(Type(), axis::category<>({A, B})); auto c =
make_histogram<adaptive_storage>(Type(), axis::category<>({A, B}));
BOOST_TEST_EQ(c.axis().size(), 2); BOOST_TEST_EQ(c.axis().size(), 2);
BOOST_TEST_EQ(c.axis().shape(), 2); BOOST_TEST_EQ(c.axis().shape(), 2);
BOOST_TEST_EQ(c.axis().index(A), 0); BOOST_TEST_EQ(c.axis().index(A), 0);
@ -227,7 +230,8 @@ void run_tests() {
BOOST_TEST(c != b); BOOST_TEST(c != b);
BOOST_TEST(a == c); BOOST_TEST(a == c);
BOOST_TEST(c == a); BOOST_TEST(c == a);
auto d = make_histogram<adaptive_storage>(Type(), axis::regular<>(2, 0, 1)); auto d =
make_histogram<adaptive_storage>(Type(), axis::regular<>(2, 0, 1));
BOOST_TEST(c != d); BOOST_TEST(c != d);
BOOST_TEST(d != c); BOOST_TEST(d != c);
c(0); c(0);
@ -425,8 +429,8 @@ void run_tests() {
// add_1 // add_1
{ {
auto a = make_histogram<adaptive_storage>(Type(), axis::integer<>(0, 2)); auto a = make_histogram<adaptive_storage>(Type(), axis::integer<>(0, 2));
auto b = auto b = make_histogram<array_storage<unsigned>>(Type(),
make_histogram<array_storage<unsigned>>(Type(), axis::integer<>(0, 2)); axis::integer<>(0, 2));
a(0); // 1 0 a(0); // 1 0
b(1); // 0 1 b(1); // 0 1
auto a2 = a; auto a2 = a;
@ -477,8 +481,8 @@ void run_tests() {
{ {
auto a = auto a =
make_histogram<array_storage<char>>(Type(), axis::integer<>(-1, 2)); make_histogram<array_storage<char>>(Type(), axis::integer<>(-1, 2));
auto b = auto b = make_histogram<array_storage<unsigned>>(Type(),
make_histogram<array_storage<unsigned>>(Type(), axis::integer<>(-1, 2)); axis::integer<>(-1, 2));
a(-1); a(-1);
b(1); b(1);
auto c = a; auto c = a;
@ -896,8 +900,8 @@ void run_mixed_tests() {
{ {
auto a = make_histogram<adaptive_storage>(T1{}, axis::regular<>{3, 0, 3}, auto a = make_histogram<adaptive_storage>(T1{}, axis::regular<>{3, 0, 3},
axis::integer<>(0, 2)); axis::integer<>(0, 2));
auto b = make_histogram<array_storage<int>>(T2{}, axis::regular<>{3, 0, 3}, auto b = make_histogram<array_storage<int>>(
axis::integer<>(0, 2)); T2{}, axis::regular<>{3, 0, 3}, axis::integer<>(0, 2));
BOOST_TEST_EQ(a, b); BOOST_TEST_EQ(a, b);
auto b2 = make_histogram<adaptive_storage>(T2{}, axis::integer<>{0, 3}, auto b2 = make_histogram<adaptive_storage>(T2{}, axis::integer<>{0, 3},
axis::integer<>(0, 2)); axis::integer<>(0, 2));
@ -926,8 +930,8 @@ void run_mixed_tests() {
{ {
auto a = make_histogram<adaptive_storage>(T1{}, axis::regular<>{3, 0, 3}, auto a = make_histogram<adaptive_storage>(T1{}, axis::regular<>{3, 0, 3},
axis::integer<>(0, 2)); axis::integer<>(0, 2));
auto b = make_histogram<array_storage<int>>(T2{}, axis::regular<>{3, 0, 3}, auto b = make_histogram<array_storage<int>>(
axis::integer<>(0, 2)); T2{}, axis::regular<>{3, 0, 3}, axis::integer<>(0, 2));
a(1, 1); a(1, 1);
BOOST_TEST_NE(a, b); BOOST_TEST_NE(a, b);
b = a; b = a;

View File

@ -4,11 +4,11 @@
// (See accompanying file LICENSE_1_0.txt // (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt) // or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "utility.hpp"
#include <boost/histogram/detail/index_mapper.hpp>
#include <boost/core/lightweight_test.hpp> #include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp> #include <boost/core/lightweight_test_trait.hpp>
#include <boost/histogram/detail/index_mapper.hpp>
#include <vector> #include <vector>
#include "utility.hpp"
using namespace boost::histogram::detail; using namespace boost::histogram::detail;

View File

@ -135,7 +135,8 @@ int main() {
BOOST_TEST_TRAIT_TRUE((std::is_same<copy_qualifiers<int&, long>, long&>)); BOOST_TEST_TRAIT_TRUE((std::is_same<copy_qualifiers<int&, long>, long&>));
BOOST_TEST_TRAIT_TRUE( BOOST_TEST_TRAIT_TRUE(
(std::is_same<copy_qualifiers<const int&, long>, const long&>)); (std::is_same<copy_qualifiers<const int&, long>, const long&>));
BOOST_TEST_TRAIT_TRUE((std::is_same<copy_qualifiers<int&&, long>, long&&>)); BOOST_TEST_TRAIT_TRUE(
(std::is_same<copy_qualifiers<int&&, long>, long&&>));
} }
// mp_set_union // mp_set_union
@ -153,8 +154,8 @@ int main() {
BOOST_TEST_TRAIT_TRUE((std::is_same<selection<T, i0>, std::tuple<char>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<selection<T, i0>, std::tuple<char>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<selection<T, i1>, std::tuple<int>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<selection<T, i1>, std::tuple<int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<selection<T, i2>, std::tuple<long>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<selection<T, i2>, std::tuple<long>>));
BOOST_TEST_TRAIT_TRUE( BOOST_TEST_TRAIT_TRUE((
(std::is_same<selection<T, i0, i1, i2>, std::tuple<char, int, long>>)); std::is_same<selection<T, i0, i1, i2>, std::tuple<char, int, long>>));
BOOST_TEST_TRAIT_TRUE( BOOST_TEST_TRAIT_TRUE(
(std::is_same<selection<T, i0, i1>, std::tuple<char, int>>)); (std::is_same<selection<T, i0, i1>, std::tuple<char, int>>));
BOOST_TEST_TRAIT_TRUE( BOOST_TEST_TRAIT_TRUE(

View File

@ -6,12 +6,12 @@
#include <algorithm> #include <algorithm>
#include <boost/histogram.hpp> #include <boost/histogram.hpp>
#include <boost/mp11.hpp>
#include <cstdio> #include <cstdio>
#include <ctime> #include <ctime>
#include <limits> #include <limits>
#include <random>
#include <memory> #include <memory>
#include <boost/mp11.hpp> #include <random>
using namespace boost::histogram; using namespace boost::histogram;
using boost::mp11::mp_list; using boost::mp11::mp_list;
@ -21,12 +21,10 @@ std::unique_ptr<double[]> random_array(unsigned n, int type) {
std::default_random_engine gen(1); std::default_random_engine gen(1);
if (type) { // type == 1 if (type) { // type == 1
std::normal_distribution<> d(0.5, 0.3); std::normal_distribution<> d(0.5, 0.3);
for (unsigned i = 0; i < n; ++i) for (unsigned i = 0; i < n; ++i) r[i] = d(gen);
r[i] = d(gen);
} else { // type == 0 } else { // type == 0
std::uniform_real_distribution<> d(0.0, 1.0); std::uniform_real_distribution<> d(0.0, 1.0);
for (unsigned i = 0; i < n; ++i) for (unsigned i = 0; i < n; ++i) r[i] = d(gen);
r[i] = d(gen);
} }
return r; return r;
} }
@ -58,8 +56,7 @@ double compare_1d(unsigned n, int distrib) {
for (unsigned k = 0; k < 20; ++k) { for (unsigned k = 0; k < 20; ++k) {
auto h = Histogram(axis::regular<>(100, 0, 1)); auto h = Histogram(axis::regular<>(100, 0, 1));
auto t = clock(); auto t = clock();
for (unsigned i = 0; i < n; ++i) for (unsigned i = 0; i < n; ++i) h(r[i]);
h(r[i]);
t = clock() - t; t = clock() - t;
best = std::min(best, double(t) / CLOCKS_PER_SEC); best = std::min(best, double(t) / CLOCKS_PER_SEC);
} }
@ -73,10 +70,10 @@ double compare_2d(unsigned n, int distrib) {
auto best = std::numeric_limits<double>::max(); auto best = std::numeric_limits<double>::max();
for (unsigned k = 0; k < 20; ++k) { for (unsigned k = 0; k < 20; ++k) {
auto h = Histogram(axis::regular<>(100, 0, 1), axis::regular<>(100, 0, 1)); auto h =
Histogram(axis::regular<>(100, 0, 1), axis::regular<>(100, 0, 1));
auto t = clock(); auto t = clock();
for (unsigned i = 0; i < n / 2; ++i) for (unsigned i = 0; i < n / 2; ++i) h(r[2 * i], r[2 * i + 1]);
h(r[2 * i], r[2 * i + 1]);
t = clock() - t; t = clock() - t;
best = std::min(best, double(t) / CLOCKS_PER_SEC); best = std::min(best, double(t) / CLOCKS_PER_SEC);
} }
@ -136,9 +133,8 @@ int main() {
else else
printf("normal distribution\n"); printf("normal distribution\n");
printf("hs_ss %.3f\n", printf("hs_ss %.3f\n",
compare_1d< compare_1d<static_histogram<mp_list<axis::regular<>>,
static_histogram<mp_list<axis::regular<>>, array_storage<int>>>( array_storage<int>>>(nfill, itype));
nfill, itype));
printf("hs_sd %.3f\n", printf("hs_sd %.3f\n",
compare_1d< compare_1d<
static_histogram<mp_list<axis::regular<>>, adaptive_storage>>( static_histogram<mp_list<axis::regular<>>, adaptive_storage>>(
@ -147,8 +143,8 @@ int main() {
compare_1d<dynamic_histogram<axis::types, array_storage<int>>>( compare_1d<dynamic_histogram<axis::types, array_storage<int>>>(
nfill, itype)); nfill, itype));
printf("hd_sd %.3f\n", printf("hd_sd %.3f\n",
compare_1d<dynamic_histogram<axis::types, adaptive_storage>>(nfill, compare_1d<dynamic_histogram<axis::types, adaptive_storage>>(
itype)); nfill, itype));
} }
printf("2D\n"); printf("2D\n");
@ -169,8 +165,8 @@ int main() {
compare_2d<dynamic_histogram<axis::types, array_storage<int>>>( compare_2d<dynamic_histogram<axis::types, array_storage<int>>>(
nfill, itype)); nfill, itype));
printf("hd_sd %.3f\n", printf("hd_sd %.3f\n",
compare_2d<dynamic_histogram<axis::types, adaptive_storage>>(nfill, compare_2d<dynamic_histogram<axis::types, adaptive_storage>>(
itype)); nfill, itype));
} }
printf("3D\n"); printf("3D\n");
@ -191,8 +187,8 @@ int main() {
compare_3d<dynamic_histogram<axis::types, array_storage<int>>>( compare_3d<dynamic_histogram<axis::types, array_storage<int>>>(
nfill, itype)); nfill, itype));
printf("hd_sd %.3f\n", printf("hd_sd %.3f\n",
compare_3d<dynamic_histogram<axis::types, adaptive_storage>>(nfill, compare_3d<dynamic_histogram<axis::types, adaptive_storage>>(
itype)); nfill, itype));
} }
printf("6D\n"); printf("6D\n");
@ -215,7 +211,7 @@ int main() {
compare_6d<dynamic_histogram<axis::types, array_storage<int>>>( compare_6d<dynamic_histogram<axis::types, array_storage<int>>>(
nfill, itype)); nfill, itype));
printf("hd_sd %.3f\n", printf("hd_sd %.3f\n",
compare_6d<dynamic_histogram<axis::types, adaptive_storage>>(nfill, compare_6d<dynamic_histogram<axis::types, adaptive_storage>>(
itype)); nfill, itype));
} }
} }

View File

@ -11,20 +11,18 @@
#include <cstdio> #include <cstdio>
#include <ctime> #include <ctime>
#include <limits> #include <limits>
#include <random>
#include <memory> #include <memory>
#include <random>
std::unique_ptr<double[]> random_array(unsigned n, int type) { std::unique_ptr<double[]> random_array(unsigned n, int type) {
std::unique_ptr<double[]> r(new double[n]); std::unique_ptr<double[]> r(new double[n]);
std::default_random_engine gen(1); std::default_random_engine gen(1);
if (type) { // type == 1 if (type) { // type == 1
std::normal_distribution<> d(0.5, 0.3); std::normal_distribution<> d(0.5, 0.3);
for (unsigned i = 0; i < n; ++i) for (unsigned i = 0; i < n; ++i) r[i] = d(gen);
r[i] = d(gen);
} else { // type == 0 } else { // type == 0
std::uniform_real_distribution<> d(0.0, 1.0); std::uniform_real_distribution<> d(0.0, 1.0);
for (unsigned i = 0; i < n; ++i) for (unsigned i = 0; i < n; ++i) r[i] = d(gen);
r[i] = d(gen);
} }
return r; return r;
} }
@ -37,8 +35,7 @@ void compare_1d(unsigned n, int distrib) {
gsl_histogram* h = gsl_histogram_alloc(100); gsl_histogram* h = gsl_histogram_alloc(100);
gsl_histogram_set_ranges_uniform(h, 0, 1); gsl_histogram_set_ranges_uniform(h, 0, 1);
auto t = clock(); auto t = clock();
for (unsigned i = 0; i < n; ++i) for (unsigned i = 0; i < n; ++i) gsl_histogram_increment(h, r[i]);
gsl_histogram_increment(h, r[i]);
t = clock() - t; t = clock() - t;
best = std::min(best, double(t) / CLOCKS_PER_SEC); best = std::min(best, double(t) / CLOCKS_PER_SEC);
gsl_histogram_free(h); gsl_histogram_free(h);

View File

@ -13,20 +13,18 @@
#include <cstdio> #include <cstdio>
#include <ctime> #include <ctime>
#include <limits> #include <limits>
#include <random>
#include <memory> #include <memory>
#include <random>
std::unique_ptr<double[]> random_array(unsigned n, int type) { std::unique_ptr<double[]> random_array(unsigned n, int type) {
std::unique_ptr<double[]> r(new double[n]); std::unique_ptr<double[]> r(new double[n]);
std::default_random_engine gen(1); std::default_random_engine gen(1);
if (type) { // type == 1 if (type) { // type == 1
std::normal_distribution<> d(0.5, 0.3); std::normal_distribution<> d(0.5, 0.3);
for (unsigned i = 0; i < n; ++i) for (unsigned i = 0; i < n; ++i) r[i] = d(gen);
r[i] = d(gen);
} else { // type == 0 } else { // type == 0
std::uniform_real_distribution<> d(0.0, 1.0); std::uniform_real_distribution<> d(0.0, 1.0);
for (unsigned i = 0; i < n; ++i) for (unsigned i = 0; i < n; ++i) r[i] = d(gen);
r[i] = d(gen);
} }
return r; return r;
} }
@ -38,8 +36,7 @@ void compare_1d(unsigned n, int distrib) {
for (unsigned k = 0; k < 20; ++k) { for (unsigned k = 0; k < 20; ++k) {
TH1I hroot("", "", 100, 0, 1); TH1I hroot("", "", 100, 0, 1);
auto t = clock(); auto t = clock();
for (unsigned i = 0; i < n; ++i) for (unsigned i = 0; i < n; ++i) hroot.Fill(r[i]);
hroot.Fill(r[i]);
t = clock() - t; t = clock() - t;
best_root = std::min(best_root, double(t) / CLOCKS_PER_SEC); best_root = std::min(best_root, double(t) / CLOCKS_PER_SEC);
} }
@ -53,8 +50,7 @@ void compare_2d(unsigned n, int distrib) {
for (unsigned k = 0; k < 20; ++k) { for (unsigned k = 0; k < 20; ++k) {
TH2I hroot("", "", 100, 0, 1, 100, 0, 1); TH2I hroot("", "", 100, 0, 1, 100, 0, 1);
auto t = clock(); auto t = clock();
for (unsigned i = 0; i < n / 2; ++i) for (unsigned i = 0; i < n / 2; ++i) hroot.Fill(r[2 * i], r[2 * i + 1]);
hroot.Fill(r[2 * i], r[2 * i + 1]);
t = clock() - t; t = clock() - t;
best_root = std::min(best_root, double(t) / CLOCKS_PER_SEC); best_root = std::min(best_root, double(t) / CLOCKS_PER_SEC);
} }
@ -87,9 +83,7 @@ void compare_6d(unsigned n, int distrib) {
THnI hroot("", "", 6, &bin.front(), &min.front(), &max.front()); THnI hroot("", "", 6, &bin.front(), &min.front(), &max.front());
auto t = clock(); auto t = clock();
for (unsigned i = 0; i < n / 6; ++i) { for (unsigned i = 0; i < n / 6; ++i) { hroot.Fill(r.get() + 6 * i); }
hroot.Fill(r.get() + 6 * i);
}
t = clock() - t; t = clock() - t;
best_root = std::min(best_root, double(t) / CLOCKS_PER_SEC); best_root = std::min(best_root, double(t) / CLOCKS_PER_SEC);
} }

View File

@ -22,8 +22,7 @@ namespace std { // never add to std, we only do it to get ADL working
template <typename T> template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) { ostream& operator<<(ostream& os, const vector<T>& v) {
os << "[ "; os << "[ ";
for (const auto& x : v) for (const auto& x : v) os << x << " ";
os << x << " ";
os << "]"; os << "]";
return os; return os;
} }