mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-10 15:24:05 +00:00
clang-format everything
This commit is contained in:
parent
47d4d85301
commit
d4dbae92f5
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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_;
|
||||||
|
@ -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) {}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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> {
|
||||||
|
@ -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_;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>,
|
||||||
|
@ -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>
|
||||||
|
@ -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) {}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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_;
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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<>>());
|
||||||
|
@ -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);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
@ -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}};
|
||||||
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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}));
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user