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
@ -4,80 +4,75 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main(int, char**) {
|
int main(int, char**) {
|
||||||
namespace bh = boost::histogram;
|
namespace bh = boost::histogram;
|
||||||
using namespace bh::literals; // enables _c suffix
|
using namespace bh::literals; // enables _c suffix
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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
|
||||||
auto data = { -0.5, 1.1, 0.3, 1.7 };
|
auto data = {-0.5, 1.1, 0.3, 1.7};
|
||||||
std::for_each(data.begin(), data.end(), h);
|
std::for_each(data.begin(), data.end(), h);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
a regular axis is a sequence of semi-open bins; extra under- and
|
a regular axis is a sequence of semi-open bins; extra under- and
|
||||||
overflow bins extend the axis in the default configuration
|
overflow bins extend the axis in the default configuration
|
||||||
index : -1 0 1 2 3 4 5 6
|
index : -1 0 1 2 3 4 5 6
|
||||||
bin edge: -inf -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 inf
|
bin edge: -inf -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 inf
|
||||||
*/
|
*/
|
||||||
h(-1.5); // put in underflow bin -1
|
h(-1.5); // put in underflow bin -1
|
||||||
h(-1.0); // put in bin 0, bin interval is semi-open
|
h(-1.0); // put in bin 0, bin interval is semi-open
|
||||||
h(2.0); // put in overflow bin 6, bin interval is semi-open
|
h(2.0); // put in overflow bin 6, bin interval is semi-open
|
||||||
h(20.0); // put in overflow bin 6
|
h(20.0); // put in overflow bin 6
|
||||||
|
|
||||||
/*
|
/*
|
||||||
do a weighted fill using bh::weight, a wrapper for any type,
|
do a weighted fill using bh::weight, a wrapper for any type,
|
||||||
which may appear at the beginning of the argument list
|
which may appear at the beginning of the argument list
|
||||||
*/
|
*/
|
||||||
h(bh::weight(1.0), 0.1);
|
h(bh::weight(1.0), 0.1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
iterate over bins with a fancy histogram iterator
|
iterate over bins with a fancy histogram iterator
|
||||||
- order in which bins are iterated over is an implementation detail
|
- order in which bins are iterated over is an implementation detail
|
||||||
- iterator dereferences to histogram::element_type, which is defined by
|
- iterator dereferences to histogram::element_type, which is defined by
|
||||||
its storage class; by default something with value() and
|
its storage class; by default something with value() and
|
||||||
variance() methods; the first returns the
|
variance() methods; the first returns the
|
||||||
actual count, the second returns a variance estimate of the count
|
actual count, the second returns a variance estimate of the count
|
||||||
(see Rationale section for what this means)
|
(see Rationale section for what this means)
|
||||||
- idx(N) method returns the index of the N-th axis
|
- idx(N) method returns the index of the N-th axis
|
||||||
- bin(N_c) method returns current bin of N-th axis; the suffx _c turns
|
- bin(N_c) method returns current bin of N-th axis; the suffx _c turns
|
||||||
the argument into a compile-time number, which is needed to return
|
the argument into a compile-time number, which is needed to return
|
||||||
different `bin_type`s for different axes
|
different `bin_type`s for different axes
|
||||||
- `bin_type` usually is a semi-open interval representing the bin, whose
|
- `bin_type` usually is a semi-open interval representing the bin, whose
|
||||||
edges can be accessed with methods `lower()` and `upper()`, but the
|
edges can be accessed with methods `lower()` and `upper()`, but the
|
||||||
implementation depends on the axis, please look it up in the reference
|
implementation depends on the axis, please look it up in the reference
|
||||||
*/
|
*/
|
||||||
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)
|
<< std::endl;
|
||||||
<< it->value() << " +/- "
|
}
|
||||||
<< std::setprecision(3) << std::sqrt(it->variance())
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* program output: (note that under- and overflow bins appear at the end)
|
/* program output: (note that under- and overflow bins appear at the end)
|
||||||
|
|
||||||
bin 0 x in [-1.0, -0.5): 1 +/- 1
|
bin 0 x in [-1.0, -0.5): 1 +/- 1
|
||||||
bin 1 x in [-0.5, 0.0): 0 +/- 0
|
bin 1 x in [-0.5, 0.0): 0 +/- 0
|
||||||
bin 2 x in [ 0.0, 0.5): 1 +/- 1
|
bin 2 x in [ 0.0, 0.5): 1 +/- 1
|
||||||
bin 3 x in [ 0.5, 1.0): 0 +/- 0
|
bin 3 x in [ 0.5, 1.0): 0 +/- 0
|
||||||
bin 4 x in [ 1.0, 1.5): 0 +/- 0
|
bin 4 x in [ 1.0, 1.5): 0 +/- 0
|
||||||
bin 5 x in [ 1.5, 2.0): 0 +/- 0
|
bin 5 x in [ 1.5, 2.0): 0 +/- 0
|
||||||
bin 6 x in [ 2.0, inf): 2 +/- 1.41421
|
bin 6 x in [ 2.0, inf): 2 +/- 1.41421
|
||||||
bin -1 x in [-inf, -1): 1 +/- 1
|
bin -1 x in [-inf, -1): 1 +/- 1
|
||||||
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -7,50 +7,43 @@
|
|||||||
namespace bh = boost::histogram;
|
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
|
||||||
h(bh::weight(3), 0.5, 2.5); // bin index 1, 0
|
h(bh::weight(3), 0.5, 2.5); // bin index 1, 0
|
||||||
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() << " "
|
<< std::endl;
|
||||||
<< h.at(1, 1).variance()
|
// prints: 1 4 9 16
|
||||||
<< std::endl;
|
|
||||||
// prints: 1 4 9 16
|
|
||||||
|
|
||||||
// you can also make a copy of the type that holds the bin count
|
// you can also make a copy of the type that holds the bin count
|
||||||
auto c11 = h.at(1, 1);
|
auto c11 = h.at(1, 1);
|
||||||
std::cout << c11.value() << " " << c11.variance() << std::endl;
|
std::cout << c11.value() << " " << c11.variance() << std::endl;
|
||||||
// prints: 4 16
|
// prints: 4 16
|
||||||
|
|
||||||
// histogram also supports access via container; using a container of
|
// histogram also supports access via container; using a container of
|
||||||
// wrong size trips an assertion in debug mode
|
// wrong size trips an assertion in debug mode
|
||||||
auto idx = {0, 1};
|
auto idx = {0, 1};
|
||||||
std::cout << h.at(idx).value() << std::endl;
|
std::cout << h.at(idx).value() << std::endl;
|
||||||
// prints: 2
|
// prints: 2
|
||||||
|
|
||||||
// histogram also provides extended iterators
|
// histogram also provides extended iterators
|
||||||
auto sum = std::accumulate(h.begin(), h.end(),
|
auto sum = std::accumulate(h.begin(), h.end(),
|
||||||
typename decltype(h)::element_type(0));
|
typename decltype(h)::element_type(0));
|
||||||
std::cout << sum.value() << " " << sum.variance() << std::endl;
|
std::cout << sum.value() << " " << sum.variance() << std::endl;
|
||||||
// prints: 10 30
|
// prints: 10 30
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -5,13 +5,12 @@
|
|||||||
namespace bh = boost::histogram;
|
namespace bh = boost::histogram;
|
||||||
|
|
||||||
int main() {
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -5,10 +5,11 @@
|
|||||||
namespace bh = boost::histogram;
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -7,36 +7,33 @@ namespace bh = boost::histogram;
|
|||||||
|
|
||||||
// custom axis, which adapts builtin integer axis
|
// custom axis, which adapts builtin integer axis
|
||||||
struct custom_axis : public bh::axis::integer<> {
|
struct custom_axis : public bh::axis::integer<> {
|
||||||
using value_type = const char*; // type that is fed to the axis
|
using value_type = const char*; // type that is fed to the axis
|
||||||
|
|
||||||
using integer::integer; // inherit ctors of base
|
using integer::integer; // inherit ctors of base
|
||||||
|
|
||||||
// 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() {
|
||||||
auto h = bh::make_static_histogram(custom_axis(0, 3));
|
auto h = bh::make_static_histogram(custom_axis(0, 3));
|
||||||
h("-10");
|
h("-10");
|
||||||
h("0");
|
h("0");
|
||||||
h("1");
|
h("1");
|
||||||
h("9");
|
h("9");
|
||||||
|
|
||||||
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:
|
||||||
bin 0 [0, 1) 1
|
bin 0 [0, 1) 1
|
||||||
bin 1 [1, 2] 1
|
bin 1 [1, 2] 1
|
||||||
bin 2 [2, 3] 0
|
bin 2 [2, 3] 0
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -6,12 +6,11 @@
|
|||||||
namespace bh = boost::histogram;
|
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,38 +1,37 @@
|
|||||||
//[ 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;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
auto h = bh::make_static_histogram(bh::axis::integer<>(0, 4),
|
auto h = bh::make_static_histogram(bh::axis::integer<>(0, 4),
|
||||||
bh::axis::regular<>(10, 0, 5));
|
bh::axis::regular<>(10, 0, 5));
|
||||||
|
|
||||||
// fill histogram, number of arguments must be equal to number of axes
|
// fill histogram, number of arguments must be equal to number of axes
|
||||||
h(0, 1.1); // increases bin counter by one
|
h(0, 1.1); // increases bin counter by one
|
||||||
h(bh::weight(2), 3, 3.4); // increase bin counter by 2 instead of 1
|
h(bh::weight(2), 3, 3.4); // increase bin counter by 2 instead of 1
|
||||||
|
|
||||||
// histogram also supports fills from a container of values; a container
|
// histogram also supports fills from a container of values; a container
|
||||||
// of wrong size trips an assertion in debug mode
|
// of wrong size trips an assertion in debug mode
|
||||||
auto xy1 = std::make_pair(4, 3.1);
|
auto xy1 = std::make_pair(4, 3.1);
|
||||||
h(xy1);
|
h(xy1);
|
||||||
auto xy2 = std::vector<double>({3.0, 4.9});
|
auto xy2 = std::vector<double>({3.0, 4.9});
|
||||||
h(xy2);
|
h(xy2);
|
||||||
|
|
||||||
// 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 =
|
||||||
auto h2 = std::for_each(input_data.begin(), input_data.end(),
|
std::for_each(input_data.begin(), input_data.end(),
|
||||||
bh::make_static_histogram(
|
bh::make_static_histogram(bh::axis::integer<>(0, 4),
|
||||||
bh::axis::integer<>(0, 4),
|
bh::axis::regular<>(10, 0, 5)));
|
||||||
bh::axis::regular<>(10, 0, 5)));
|
// h is filled
|
||||||
// h is filled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -6,52 +6,52 @@
|
|||||||
namespace bh = boost::histogram;
|
namespace bh = boost::histogram;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// make two histograms
|
// make two histograms
|
||||||
auto h1 = bh::make_static_histogram(bh::axis::regular<>(2, -1, 1));
|
auto h1 = bh::make_static_histogram(bh::axis::regular<>(2, -1, 1));
|
||||||
auto h2 = bh::make_static_histogram(bh::axis::regular<>(2, -1, 1));
|
auto h2 = bh::make_static_histogram(bh::axis::regular<>(2, -1, 1));
|
||||||
|
|
||||||
h1(-0.5); // counts are: 1 0
|
h1(-0.5); // counts are: 1 0
|
||||||
h2(0.5); // counts are: 0 1
|
h2(0.5); // counts are: 0 1
|
||||||
|
|
||||||
// add them
|
// add them
|
||||||
auto h3 = h1;
|
auto h3 = h1;
|
||||||
h3 += h2; // counts are: 1 1
|
h3 += h2; // counts are: 1 1
|
||||||
|
|
||||||
// adding multiple histograms at once is efficient and does not create
|
// adding multiple histograms at once is efficient and does not create
|
||||||
// superfluous temporaries since operator+ functions are overloaded to
|
// superfluous temporaries since operator+ functions are overloaded to
|
||||||
// accept and return rvalue references where possible
|
// accept and return rvalue references where possible
|
||||||
auto h4 = h1 + h2 + h3; // counts are: 2 2
|
auto h4 = h1 + h2 + h3; // counts are: 2 2
|
||||||
|
|
||||||
std::cout << h4.at(0).value() << " " << h4.at(1).value() << std::endl;
|
std::cout << h4.at(0).value() << " " << h4.at(1).value() << std::endl;
|
||||||
// prints: 2 2
|
// prints: 2 2
|
||||||
|
|
||||||
// multiply by number
|
// multiply by number
|
||||||
h4 *= 2; // counts are: 4 4
|
h4 *= 2; // counts are: 4 4
|
||||||
|
|
||||||
// divide by number
|
// divide by number
|
||||||
auto h5 = h4 / 4; // counts are: 1 1
|
auto h5 = h4 / 4; // counts are: 1 1
|
||||||
|
|
||||||
std::cout << h5.at(0).value() << " " << h5.at(1).value() << std::endl;
|
std::cout << h5.at(0).value() << " " << h5.at(1).value() << std::endl;
|
||||||
// prints: 1 1
|
// prints: 1 1
|
||||||
|
|
||||||
// compare histograms
|
// compare histograms
|
||||||
std::cout << (h4 == 4 * h5) << " " << (h4 != h5) << std::endl;
|
std::cout << (h4 == 4 * h5) << " " << (h4 != h5) << std::endl;
|
||||||
// prints: 1 1
|
// prints: 1 1
|
||||||
|
|
||||||
// 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:
|
||||||
value 2 2
|
value 2 2
|
||||||
variance 4 2
|
variance 4 2
|
||||||
0
|
0
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -7,56 +7,51 @@ 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(
|
||||||
auto result = typename bh::histogram<Ts...>::element_type(0);
|
const bh::histogram<Ts...>& h) {
|
||||||
for (auto x : h)
|
auto result = typename bh::histogram<Ts...>::element_type(0);
|
||||||
result += x;
|
for (auto x : h) result += x;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
using namespace bh::literals; // enables _c suffix
|
using namespace bh::literals; // enables _c suffix
|
||||||
|
|
||||||
// make a 2d histogram
|
// make a 2d histogram
|
||||||
auto h = bh::make_static_histogram(bh::axis::regular<>(3, -1, 1),
|
auto h = bh::make_static_histogram(bh::axis::regular<>(3, -1, 1),
|
||||||
bh::axis::integer<>(0, 4));
|
bh::axis::integer<>(0, 4));
|
||||||
|
|
||||||
h(-0.9, 0);
|
h(-0.9, 0);
|
||||||
h(0.9, 3);
|
h(0.9, 3);
|
||||||
h(0.1, 2);
|
h(0.1, 2);
|
||||||
|
|
||||||
auto hr0 = h.reduce_to(0_c); // keep only first axis
|
auto hr0 = h.reduce_to(0_c); // keep only first axis
|
||||||
auto hr1 = h.reduce_to(1_c); // keep only second axis
|
auto hr1 = h.reduce_to(1_c); // keep only second axis
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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;
|
|
||||||
}
|
|
||||||
// prints: 1 0 0
|
|
||||||
// 0 0 0
|
|
||||||
// 0 1 0
|
|
||||||
// 0 0 1
|
|
||||||
|
|
||||||
for (auto xi : hr0.axis())
|
|
||||||
std::cout << hr0.at(xi).value() << " ";
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
// prints: 1 1 1
|
}
|
||||||
|
// prints: 1 0 0
|
||||||
|
// 0 0 0
|
||||||
|
// 0 1 0
|
||||||
|
// 0 0 1
|
||||||
|
|
||||||
for (auto yi : hr1.axis())
|
for (auto xi : hr0.axis()) std::cout << hr0.at(xi).value() << " ";
|
||||||
std::cout << hr1.at(yi).value() << " ";
|
std::cout << std::endl;
|
||||||
std::cout << std::endl;
|
// prints: 1 1 1
|
||||||
// prints: 1 0 1 1
|
|
||||||
|
for (auto yi : hr1.axis()) std::cout << hr1.at(yi).value() << " ";
|
||||||
|
std::cout << std::endl;
|
||||||
|
// prints: 1 0 1 1
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -1,42 +1,42 @@
|
|||||||
//[ 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;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
auto a = bh::make_static_histogram(bh::axis::regular<>(3, -1, 1, "r"),
|
auto a = bh::make_static_histogram(bh::axis::regular<>(3, -1, 1, "r"),
|
||||||
bh::axis::integer<>(0, 2, "i"));
|
bh::axis::integer<>(0, 2, "i"));
|
||||||
a(0.5, 1);
|
a(0.5, 1);
|
||||||
|
|
||||||
std::string buf; // holds persistent representation
|
std::string buf; // holds persistent representation
|
||||||
|
|
||||||
// store histogram
|
// store histogram
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
boost::archive::text_oarchive oa(os);
|
boost::archive::text_oarchive oa(os);
|
||||||
oa << a;
|
oa << a;
|
||||||
buf = os.str();
|
buf = os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto b = decltype(a)(); // create a default-constructed second histogram
|
auto b = decltype(a)(); // create a default-constructed second histogram
|
||||||
|
|
||||||
std::cout << "before restore " << (a == b) << std::endl;
|
std::cout << "before restore " << (a == b) << std::endl;
|
||||||
// prints: before restore 0
|
// prints: before restore 0
|
||||||
|
|
||||||
// load histogram
|
// load histogram
|
||||||
{
|
{
|
||||||
std::istringstream is(buf);
|
std::istringstream is(buf);
|
||||||
boost::archive::text_iarchive ia(is);
|
boost::archive::text_iarchive ia(is);
|
||||||
ia >> b;
|
ia >> b;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "after restore " << (a == b) << std::endl;
|
std::cout << "after restore " << (a == b) << std::endl;
|
||||||
// prints: after restore 1
|
// prints: after restore 1
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -7,33 +7,32 @@
|
|||||||
namespace bh = boost::histogram;
|
namespace bh = boost::histogram;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
namespace axis = boost::histogram::axis;
|
namespace axis = boost::histogram::axis;
|
||||||
|
|
||||||
enum { A, B, C };
|
enum { A, B, C };
|
||||||
|
|
||||||
auto h = bh::make_static_histogram(
|
auto h = bh::make_static_histogram(
|
||||||
axis::regular<>(2, -1, 1, "regular1", axis::uoflow::off),
|
axis::regular<>(2, -1, 1, "regular1", axis::uoflow::off),
|
||||||
axis::regular<double, axis::transform::log>(2, 1, 10, "regular2"),
|
axis::regular<double, axis::transform::log>(2, 1, 10, "regular2"),
|
||||||
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;
|
||||||
|
|
||||||
/* prints:
|
/* prints:
|
||||||
|
|
||||||
histogram(
|
histogram(
|
||||||
regular(2, -1, 1, label='regular1', uoflow=False),
|
regular(2, -1, 1, label='regular1', uoflow=False),
|
||||||
regular_log(2, 1, 10, label='regular2'),
|
regular_log(2, 1, 10, label='regular2'),
|
||||||
circular(4, phase=0.1, perimeter=1, label='polar'),
|
circular(4, phase=0.1, perimeter=1, label='polar'),
|
||||||
variable(-1, 0, 1, label='variable', uoflow=False),
|
variable(-1, 0, 1, label='variable', uoflow=False),
|
||||||
category(0, 1, 2, label='category'),
|
category(0, 1, 2, label='category'),
|
||||||
integer(-1, 1, label='integer', uoflow=False),
|
integer(-1, 1, label='integer', uoflow=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -6,15 +6,15 @@
|
|||||||
namespace bh = boost::histogram;
|
namespace bh = boost::histogram;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// create vector of axes, axis::any is a polymorphic axis type
|
// create vector of axes, axis::any is a polymorphic axis type
|
||||||
auto v = std::vector<bh::axis::any_std>();
|
auto v = std::vector<bh::axis::any_std>();
|
||||||
v.push_back(bh::axis::regular<>(100, -1, 1));
|
v.push_back(bh::axis::regular<>(100, -1, 1));
|
||||||
v.push_back(bh::axis::integer<>(1, 7));
|
v.push_back(bh::axis::integer<>(1, 7));
|
||||||
|
|
||||||
// create dynamic histogram (make_static_histogram be used with iterators)
|
// create dynamic histogram (make_static_histogram be used with iterators)
|
||||||
auto h = bh::make_dynamic_histogram(v.begin(), v.end());
|
auto h = bh::make_dynamic_histogram(v.begin(), v.end());
|
||||||
|
|
||||||
// do something with h
|
// do something with h
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
namespace bh = boost::histogram;
|
namespace bh = boost::histogram;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
/*
|
/*
|
||||||
create a 1d-histogram in default configuration which
|
create a 1d-histogram in default configuration which
|
||||||
covers the real line from -1 to 1 in 100 bins, the same
|
covers the real line from -1 to 1 in 100 bins, the same
|
||||||
call with `make_dynamic_histogram` would also work
|
call with `make_dynamic_histogram` would also work
|
||||||
*/
|
*/
|
||||||
auto h = bh::make_static_histogram(bh::axis::regular<>(100, -1, 1));
|
auto h = bh::make_static_histogram(bh::axis::regular<>(100, -1, 1));
|
||||||
|
|
||||||
// do something with h
|
// do something with h
|
||||||
}
|
}
|
||||||
|
|
||||||
//]
|
//]
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ enum class uoflow { off = 0, only_oflow = 1, on = 2 };
|
|||||||
|
|
||||||
/// Base class for all axes
|
/// Base class for all axes
|
||||||
class base {
|
class base {
|
||||||
public:
|
public:
|
||||||
/// Returns the number of bins without overflow/underflow.
|
/// Returns the number of bins without overflow/underflow.
|
||||||
int size() const noexcept { return size_; }
|
int size() const noexcept { return size_; }
|
||||||
/// Returns the number of bins, including overflow/underflow if enabled.
|
/// Returns the number of bins, including overflow/underflow if enabled.
|
||||||
@ -40,14 +40,12 @@ class base {
|
|||||||
/// Change the label of an axis.
|
/// Change the label of an axis.
|
||||||
void label(string_view label) { label_.assign(label.begin(), label.end()); }
|
void label(string_view label) { label_.assign(label.begin(), label.end()); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
base(unsigned size, string_view label, axis::uoflow uo)
|
base(unsigned size, string_view label, axis::uoflow uo)
|
||||||
: 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;
|
||||||
@ -73,7 +71,7 @@ class base {
|
|||||||
return size_ == rhs.size_ && shape_ == rhs.shape_ && label_ == rhs.label_;
|
return size_ == rhs.size_ && shape_ == rhs.shape_ && label_ == rhs.label_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int size_ = 0, shape_ = 0;
|
int size_ = 0, shape_ = 0;
|
||||||
std::string label_;
|
std::string label_;
|
||||||
|
|
||||||
@ -85,7 +83,7 @@ class base {
|
|||||||
/// Iterator mixin, uses CRTP to inject iterator logic into Derived.
|
/// Iterator mixin, uses CRTP to inject iterator logic into Derived.
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
class iterator_mixin {
|
class iterator_mixin {
|
||||||
public:
|
public:
|
||||||
using const_iterator = iterator_over<Derived>;
|
using const_iterator = iterator_over<Derived>;
|
||||||
using const_reverse_iterator = reverse_iterator_over<Derived>;
|
using const_reverse_iterator = reverse_iterator_over<Derived>;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ namespace axis {
|
|||||||
|
|
||||||
template <typename Axis>
|
template <typename Axis>
|
||||||
class interval_view {
|
class interval_view {
|
||||||
public:
|
public:
|
||||||
interval_view(int idx, const Axis& axis) : idx_(idx), axis_(axis) {}
|
interval_view(int idx, const Axis& axis) : idx_(idx), axis_(axis) {}
|
||||||
|
|
||||||
interval_view(const interval_view&) = default;
|
interval_view(const interval_view&) = 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_;
|
||||||
@ -43,7 +45,7 @@ class interval_view {
|
|||||||
|
|
||||||
explicit operator int() const noexcept { return idx_; }
|
explicit operator int() const noexcept { return idx_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const int idx_;
|
const int idx_;
|
||||||
const Axis& axis_;
|
const Axis& axis_;
|
||||||
};
|
};
|
||||||
|
@ -14,17 +14,18 @@ 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;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void increment() noexcept { ++idx_; }
|
void increment() noexcept { ++idx_; }
|
||||||
void decrement() noexcept { --idx_; }
|
void decrement() noexcept { --idx_; }
|
||||||
void advance(int n) noexcept { idx_ += n; }
|
void advance(int n) noexcept { idx_ += n; }
|
||||||
@ -43,18 +44,17 @@ 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) {}
|
||||||
|
|
||||||
reverse_iterator_over(const reverse_iterator_over&) = default;
|
reverse_iterator_over(const reverse_iterator_over&) = default;
|
||||||
reverse_iterator_over& operator=(const reverse_iterator_over&) = default;
|
reverse_iterator_over& operator=(const reverse_iterator_over&) = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void increment() noexcept { --idx_; }
|
void increment() noexcept { --idx_; }
|
||||||
void decrement() noexcept { ++idx_; }
|
void decrement() noexcept { ++idx_; }
|
||||||
void advance(int n) noexcept { idx_ -= n; }
|
void advance(int n) noexcept { idx_ -= n; }
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ struct pow {
|
|||||||
return power == other.power;
|
return power == other.power;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend ::boost::serialization::access;
|
friend ::boost::serialization::access;
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive&, unsigned);
|
void serialize(Archive&, unsigned);
|
||||||
@ -114,7 +114,7 @@ template <typename RealType, typename Transform>
|
|||||||
class regular : public base,
|
class regular : public base,
|
||||||
public iterator_mixin<regular<RealType, Transform>>,
|
public iterator_mixin<regular<RealType, Transform>>,
|
||||||
Transform {
|
Transform {
|
||||||
public:
|
public:
|
||||||
using value_type = RealType;
|
using value_type = RealType;
|
||||||
using bin_type = interval_view<regular>;
|
using bin_type = interval_view<regular>;
|
||||||
|
|
||||||
@ -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.
|
||||||
@ -186,7 +183,7 @@ class regular : public base,
|
|||||||
return static_cast<const Transform&>(*this);
|
return static_cast<const Transform&>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
value_type min_ = 0.0, delta_ = 1.0;
|
value_type min_ = 0.0, delta_ = 1.0;
|
||||||
|
|
||||||
friend class ::boost::serialization::access;
|
friend class ::boost::serialization::access;
|
||||||
@ -202,7 +199,7 @@ class regular : public base,
|
|||||||
*/
|
*/
|
||||||
template <typename RealType>
|
template <typename RealType>
|
||||||
class circular : public base, public iterator_mixin<circular<RealType>> {
|
class circular : public base, public iterator_mixin<circular<RealType>> {
|
||||||
public:
|
public:
|
||||||
using value_type = RealType;
|
using value_type = RealType;
|
||||||
using bin_type = interval_view<circular>;
|
using bin_type = interval_view<circular>;
|
||||||
|
|
||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +247,7 @@ class circular : public base, public iterator_mixin<circular<RealType>> {
|
|||||||
value_type perimeter() const { return perimeter_; }
|
value_type perimeter() const { return perimeter_; }
|
||||||
value_type phase() const { return phase_; }
|
value_type phase() const { return phase_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
value_type phase_ = 0.0, perimeter_ = 1.0;
|
value_type phase_ = 0.0, perimeter_ = 1.0;
|
||||||
|
|
||||||
friend class ::boost::serialization::access;
|
friend class ::boost::serialization::access;
|
||||||
@ -265,7 +262,7 @@ class circular : public base, public iterator_mixin<circular<RealType>> {
|
|||||||
*/
|
*/
|
||||||
template <typename RealType>
|
template <typename RealType>
|
||||||
class variable : public base, public iterator_mixin<variable<RealType>> {
|
class variable : public base, public iterator_mixin<variable<RealType>> {
|
||||||
public:
|
public:
|
||||||
using value_type = RealType;
|
using value_type = RealType;
|
||||||
using bin_type = interval_view<variable>;
|
using bin_type = interval_view<variable>;
|
||||||
|
|
||||||
@ -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,13 +326,11 @@ 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());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<value_type[]> x_; // smaller size compared to std::vector
|
std::unique_ptr<value_type[]> x_; // smaller size compared to std::vector
|
||||||
|
|
||||||
friend class ::boost::serialization::access;
|
friend class ::boost::serialization::access;
|
||||||
@ -354,7 +345,7 @@ class variable : public base, public iterator_mixin<variable<RealType>> {
|
|||||||
*/
|
*/
|
||||||
template <typename IntType>
|
template <typename IntType>
|
||||||
class integer : public base, public iterator_mixin<integer<IntType>> {
|
class integer : public base, public iterator_mixin<integer<IntType>> {
|
||||||
public:
|
public:
|
||||||
using value_type = IntType;
|
using value_type = IntType;
|
||||||
using bin_type = interval_view<integer>;
|
using bin_type = interval_view<integer>;
|
||||||
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,7 +389,7 @@ class integer : public base, public iterator_mixin<integer<IntType>> {
|
|||||||
return base::operator==(o) && min_ == o.min_;
|
return base::operator==(o) && min_ == o.min_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
value_type min_ = 0;
|
value_type min_ = 0;
|
||||||
|
|
||||||
friend class ::boost::serialization::access;
|
friend class ::boost::serialization::access;
|
||||||
@ -423,7 +408,7 @@ template <typename T>
|
|||||||
class category : public base, public iterator_mixin<category<T>> {
|
class category : public base, public iterator_mixin<category<T>> {
|
||||||
using map_type = bimap<T, int>;
|
using map_type = bimap<T, int>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
using bin_type = value_view<category>;
|
using bin_type = value_view<category>;
|
||||||
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,7 +467,7 @@ class category : public base, public iterator_mixin<category<T>> {
|
|||||||
std::equal(map_->begin(), map_->end(), o.map_->begin());
|
std::equal(map_->begin(), map_->end(), o.map_->begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<map_type> map_;
|
std::unique_ptr<map_type> map_;
|
||||||
|
|
||||||
friend class ::boost::serialization::access;
|
friend class ::boost::serialization::access;
|
||||||
|
@ -16,7 +16,7 @@ namespace axis {
|
|||||||
|
|
||||||
template <typename Axis>
|
template <typename Axis>
|
||||||
class value_view {
|
class value_view {
|
||||||
public:
|
public:
|
||||||
value_view(int idx, const Axis& axis) : idx_(idx), axis_(axis) {}
|
value_view(int idx, const Axis& axis) : idx_(idx), axis_(axis) {}
|
||||||
|
|
||||||
value_view(const value_view&) = default;
|
value_view(const value_view&) = default;
|
||||||
@ -39,7 +39,7 @@ class value_view {
|
|||||||
|
|
||||||
explicit operator int() const noexcept { return idx_; }
|
explicit operator int() const noexcept { return idx_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const int idx_;
|
const int idx_;
|
||||||
const Axis& axis_;
|
const Axis& axis_;
|
||||||
};
|
};
|
||||||
|
@ -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,27 +73,28 @@ 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(
|
||||||
"cannot assign incompatible axes");
|
std::is_same<mp11::mp_list<Ts...>, mp11::mp_list<Us...>>::value,
|
||||||
|
"cannot assign incompatible axes");
|
||||||
t = u;
|
t = 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ struct index_mapper {
|
|||||||
return first < nfirst;
|
return first < nfirst;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::size_t nfirst;
|
std::size_t nfirst;
|
||||||
struct dim {
|
struct dim {
|
||||||
std::size_t stride1, stride2;
|
std::size_t stride1, stride2;
|
||||||
|
@ -55,16 +55,14 @@ 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 {};
|
||||||
|
|
||||||
template <typename T,
|
template <typename T,
|
||||||
@ -72,11 +70,10 @@ 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 {
|
||||||
struct bool_mask_impl {
|
struct bool_mask_impl {
|
||||||
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ template <typename Axes, typename Storage>
|
|||||||
class histogram<dynamic_tag, Axes, Storage> {
|
class histogram<dynamic_tag, Axes, Storage> {
|
||||||
static_assert(mp11::mp_size<Axes>::value > 0, "at least one axis required");
|
static_assert(mp11::mp_size<Axes>::value > 0, "at least one axis required");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using any_axis_type = mp11::mp_rename<Axes, axis::any>;
|
using any_axis_type = mp11::mp_rename<Axes, axis::any>;
|
||||||
using axes_type = std::vector<any_axis_type>;
|
using axes_type = std::vector<any_axis_type>;
|
||||||
using element_type = typename Storage::element_type;
|
using element_type = typename Storage::element_type;
|
||||||
@ -62,15 +62,14 @@ class histogram<dynamic_tag, Axes, Storage> {
|
|||||||
using const_iterator = iterator_over<histogram>;
|
using const_iterator = iterator_over<histogram>;
|
||||||
using iterator = const_iterator;
|
using iterator = const_iterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
histogram() = default;
|
histogram() = default;
|
||||||
histogram(const histogram&) = default;
|
histogram(const histogram&) = default;
|
||||||
histogram(histogram&&) = default;
|
histogram(histogram&&) = default;
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +273,7 @@ class histogram<dynamic_tag, Axes, Storage> {
|
|||||||
return const_iterator(*this, storage_.size());
|
return const_iterator(*this, storage_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
axes_type axes_;
|
axes_type axes_;
|
||||||
Storage storage_;
|
Storage storage_;
|
||||||
mutable detail::index_cache index_cache_;
|
mutable detail::index_cache index_cache_;
|
||||||
@ -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,11 +21,10 @@ 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) {}
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ class iterator_over
|
|||||||
return histogram_.axis(dim)[idx(dim)];
|
return histogram_.axis(dim)[idx(dim)];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool equal(const iterator_over& rhs) const noexcept {
|
bool equal(const iterator_over& rhs) const noexcept {
|
||||||
return &histogram_ == &rhs.histogram_ && idx_ == rhs.idx_;
|
return &histogram_ == &rhs.histogram_ && idx_ == rhs.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_;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ class histogram<static_tag, Axes, Storage> {
|
|||||||
using axes_size = mp11::mp_size<Axes>;
|
using axes_size = mp11::mp_size<Axes>;
|
||||||
static_assert(axes_size::value > 0, "at least one axis required");
|
static_assert(axes_size::value > 0, "at least one axis required");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using axes_type = mp11::mp_rename<Axes, std::tuple>;
|
using axes_type = mp11::mp_rename<Axes, std::tuple>;
|
||||||
using element_type = typename Storage::element_type;
|
using element_type = typename Storage::element_type;
|
||||||
using const_reference = typename Storage::const_reference;
|
using const_reference = typename Storage::const_reference;
|
||||||
@ -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,8 +250,9 @@ 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 =
|
||||||
Storage>;
|
static_histogram<detail::selection<Axes, mp11::mp_int<N>, Ns...>,
|
||||||
|
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_));
|
||||||
const auto b = detail::bool_mask<mp11::mp_int<N>, Ns...>(dim(), true);
|
const auto b = detail::bool_mask<mp11::mp_int<N>, Ns...>(dim(), true);
|
||||||
@ -264,9 +262,11 @@ 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_;
|
||||||
Storage storage_;
|
Storage storage_;
|
||||||
mutable detail::index_cache index_cache_;
|
mutable detail::index_cache index_cache_;
|
||||||
@ -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>
|
||||||
|
@ -54,7 +54,7 @@ inline T* alloc(std::size_t s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class array_base {
|
class array_base {
|
||||||
public:
|
public:
|
||||||
explicit array_base(const std::size_t s) : size(s) {}
|
explicit array_base(const std::size_t s) : size(s) {}
|
||||||
array_base() = default;
|
array_base() = default;
|
||||||
array_base(const array_base&) = default;
|
array_base(const array_base&) = default;
|
||||||
@ -72,7 +72,7 @@ class array_base {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class array : public array_base {
|
class array : public array_base {
|
||||||
public:
|
public:
|
||||||
explicit array(const std::size_t s) : array_base(s), ptr(alloc<T>(s)) {
|
explicit array(const std::size_t s) : array_base(s), ptr(alloc<T>(s)) {
|
||||||
std::fill(begin(), end(), T(0));
|
std::fill(begin(), end(), T(0));
|
||||||
}
|
}
|
||||||
@ -118,23 +118,19 @@ class array : public array_base {
|
|||||||
const T* begin() const { return ptr.get(); }
|
const T* begin() const { return ptr.get(); }
|
||||||
const T* end() const { return ptr.get() + size; }
|
const T* end() const { return ptr.get() + size; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<T[]> ptr;
|
std::unique_ptr<T[]> ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class array<void> : public array_base {
|
class array<void> : public array_base {
|
||||||
public:
|
public:
|
||||||
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>
|
||||||
@ -425,11 +416,12 @@ struct bicmp_visitor : public static_visitor<bool> {
|
|||||||
class adaptive_storage {
|
class adaptive_storage {
|
||||||
using buffer_type = detail::any_array;
|
using buffer_type = detail::any_array;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
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,9 +508,9 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,7 +520,7 @@ class adaptive_storage {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
buffer_type buffer_;
|
buffer_type buffer_;
|
||||||
|
|
||||||
friend class ::boost::python::access;
|
friend class ::boost::python::access;
|
||||||
|
@ -24,7 +24,7 @@ namespace histogram {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class array_storage {
|
class array_storage {
|
||||||
public:
|
public:
|
||||||
using element_type = T;
|
using element_type = T;
|
||||||
using const_reference = const T&;
|
using const_reference = const T&;
|
||||||
|
|
||||||
@ -81,30 +81,29 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::size_t size_ = 0;
|
std::size_t size_ = 0;
|
||||||
std::unique_ptr<element_type[]> array_;
|
std::unique_ptr<element_type[]> array_;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -21,7 +21,7 @@ namespace histogram {
|
|||||||
/// Double counter which holds a sum of weights and a sum of squared weights
|
/// Double counter which holds a sum of weights and a sum of squared weights
|
||||||
template <typename RealType>
|
template <typename RealType>
|
||||||
class weight_counter {
|
class weight_counter {
|
||||||
public:
|
public:
|
||||||
/// Beware: For performance reasons counters are not initialized
|
/// Beware: For performance reasons counters are not initialized
|
||||||
weight_counter() = default;
|
weight_counter() = default;
|
||||||
weight_counter(const weight_counter&) = default;
|
weight_counter(const weight_counter&) = default;
|
||||||
@ -108,7 +108,7 @@ class weight_counter {
|
|||||||
return static_cast<T>(w);
|
return static_cast<T>(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class ::boost::serialization::access;
|
friend class ::boost::serialization::access;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
|
@ -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,46 +137,51 @@ 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);
|
||||||
d["shape"] = shape;
|
d["shape"] = shape;
|
||||||
d["typestr"] = bp::dtype_typestr<T>();
|
d["typestr"] = bp::dtype_typestr<T>();
|
||||||
// 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,15 +198,16 @@ 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,
|
||||||
"\n:returns: bin index for the passed value",
|
":param float x: 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,
|
||||||
":returns: number of bins, excluding over-/underflow bins.",
|
":returns: number of bins, excluding over-/underflow bins.",
|
||||||
@ -227,39 +227,35 @@ 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,
|
||||||
{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);
|
uo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_axis_types() {
|
void register_axis_types() {
|
||||||
@ -268,32 +264,34 @@ void register_axis_types() {
|
|||||||
docstring_options dopt(true, true, false);
|
docstring_options dopt(true, true, false);
|
||||||
|
|
||||||
class_<generic_iterator>("generic_iterator", init<object>())
|
class_<generic_iterator>("generic_iterator", init<object>())
|
||||||
.def("__iter__", &generic_iterator::self, return_internal_reference<>())
|
.def("__iter__", &generic_iterator::self, return_internal_reference<>())
|
||||||
.def("__next__", &generic_iterator::next) // Python3
|
.def("__next__", &generic_iterator::next) // Python3
|
||||||
.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__",
|
||||||
.def("__init__", make_constructor(regular_init<bha::transform::identity>,
|
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)))
|
||||||
.def(axis_suite<bha::regular<>>());
|
.def(axis_suite<bha::regular<>>());
|
||||||
|
|
||||||
#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 \
|
||||||
"\nBinning is a O(1) operation.", \
|
"-space." \
|
||||||
no_init) \
|
"\nBinning is a O(1) operation.", \
|
||||||
.def("__init__", make_constructor(regular_init<bha::transform::x>, \
|
no_init) \
|
||||||
default_call_policies(), \
|
.def("__init__", \
|
||||||
(arg("bin"), arg("lower"), arg("upper"), \
|
make_constructor(regular_init<bha::transform::x>, \
|
||||||
arg("label") = "", arg("uoflow") = true))) \
|
default_call_policies(), \
|
||||||
|
(arg("bin"), arg("lower"), arg("upper"), \
|
||||||
|
arg("label") = "", arg("uoflow") = true))) \
|
||||||
.def(axis_suite<bha::regular<double, bha::transform::x>>())
|
.def(axis_suite<bha::regular<double, bha::transform::x>>())
|
||||||
|
|
||||||
BOOST_HISTOGRAM_PYTHON_REGULAR_CLASS(log);
|
BOOST_HISTOGRAM_PYTHON_REGULAR_CLASS(log);
|
||||||
@ -305,10 +303,11 @@ 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(
|
||||||
(arg("bin"), arg("lower"), arg("upper"), arg("power"),
|
regular_pow_init, default_call_policies(),
|
||||||
arg("label") = "", arg("uoflow") = true)))
|
(arg("bin"), arg("lower"), arg("upper"), arg("power"),
|
||||||
|
arg("label") = "", arg("uoflow") = true)))
|
||||||
.def(axis_suite<bha::regular<double, bha::transform::pow>>());
|
.def(axis_suite<bha::regular<double, bha::transform::pow>>());
|
||||||
|
|
||||||
class_<bha::circular<>>(
|
class_<bha::circular<>>(
|
||||||
@ -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<>>(
|
||||||
@ -331,7 +329,7 @@ void register_axis_types() {
|
|||||||
"\nthe problem domain allows it, prefer a regular axis.",
|
"\nthe problem domain allows it, prefer a regular axis.",
|
||||||
no_init)
|
no_init)
|
||||||
.def("__init__", raw_function(variable_init))
|
.def("__init__", raw_function(variable_init))
|
||||||
.def(init<const bha::variable<> &>())
|
.def(init<const bha::variable<>&>())
|
||||||
.def(axis_suite<bha::variable<>>());
|
.def(axis_suite<bha::variable<>>());
|
||||||
|
|
||||||
class_<bha::integer<>>(
|
class_<bha::integer<>>(
|
||||||
@ -340,10 +338,10 @@ 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<>>());
|
||||||
|
|
||||||
class_<bha::category<>>(
|
class_<bha::category<>>(
|
||||||
@ -354,6 +352,6 @@ void register_axis_types() {
|
|||||||
"\nBinning is a O(1) operation.",
|
"\nBinning is a O(1) operation.",
|
||||||
no_init)
|
no_init)
|
||||||
.def("__init__", raw_function(category_init))
|
.def("__init__", raw_function(category_init))
|
||||||
.def(init<const bha::category<> &>())
|
.def(init<const bha::category<>&>())
|
||||||
.def(axis_suite<bha::category<>>());
|
.def(axis_suite<bha::category<>>());
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
@ -44,8 +44,8 @@ public:
|
|||||||
using array = bh::detail::array<T>;
|
using array = bh::detail::array<T>;
|
||||||
|
|
||||||
struct dtype_visitor : public boost::static_visitor<str> {
|
struct dtype_visitor : public boost::static_visitor<str> {
|
||||||
list & shapes, & strides;
|
list &shapes, &strides;
|
||||||
dtype_visitor(list &sh, list &st) : shapes(sh), strides(st) {}
|
dtype_visitor(list& sh, list& st) : shapes(sh), strides(st) {}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
str operator()(const array<T>& /*unused*/) const {
|
str operator()(const array<T>& /*unused*/) const {
|
||||||
strides.append(sizeof(T));
|
strides.append(sizeof(T));
|
||||||
@ -85,26 +85,25 @@ 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] =
|
||||||
auto *buf = (double *)a.get_data();
|
bp::extract<int>(strides[i]);
|
||||||
for (auto i = 0ul; i < b.size; ++i)
|
auto* buf = (double*)a.get_data();
|
||||||
buf[i] = static_cast<double>(b[i]);
|
for (auto i = 0ul; i < b.size; ++i) buf[i] = static_cast<double>(b[i]);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static object array_interface(const pyhistogram &self) {
|
static object array_interface(const pyhistogram& self) {
|
||||||
dict d;
|
dict d;
|
||||||
list shapes;
|
list shapes;
|
||||||
list strides;
|
list strides;
|
||||||
auto &b = self.storage_.buffer_;
|
auto& b = self.storage_.buffer_;
|
||||||
d["typestr"] = boost::apply_visitor(dtype_visitor(shapes, strides), b);
|
d["typestr"] = boost::apply_visitor(dtype_visitor(shapes, strides), b);
|
||||||
for (auto i = 0u; i < self.dim(); ++i) {
|
for (auto i = 0u; i < self.dim(); ++i) {
|
||||||
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()) {
|
||||||
@ -138,9 +139,8 @@ 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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -220,18 +218,20 @@ struct span {
|
|||||||
|
|
||||||
bp::object histogram_fill(bp::tuple args, bp::dict kwargs) {
|
bp::object histogram_fill(bp::tuple args, bp::dict kwargs) {
|
||||||
const auto nargs = bp::len(args);
|
const auto nargs = bp::len(args);
|
||||||
pyhistogram &self = bp::extract<pyhistogram &>(args[0]);
|
pyhistogram& self = bp::extract<pyhistogram&>(args[0]);
|
||||||
|
|
||||||
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});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,20 +316,20 @@ 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()}));
|
||||||
}
|
}
|
||||||
|
|
||||||
bp::object histogram_at(bp::tuple args, bp::dict kwargs) {
|
bp::object histogram_at(bp::tuple args, bp::dict kwargs) {
|
||||||
const pyhistogram & self = bp::extract<const pyhistogram &>(args[0]);
|
const pyhistogram& self = bp::extract<const pyhistogram&>(args[0]);
|
||||||
|
|
||||||
if (kwargs) {
|
if (kwargs) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "no keyword arguments allowed");
|
PyErr_SetString(PyExc_RuntimeError, "no keyword arguments allowed");
|
||||||
@ -343,14 +341,15 @@ bp::object histogram_at(bp::tuple args, bp::dict kwargs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bp::object histogram_reduce_to(bp::tuple args, bp::dict kwargs) {
|
bp::object histogram_reduce_to(bp::tuple args, bp::dict kwargs) {
|
||||||
const pyhistogram &self = bp::extract<const pyhistogram &>(args[0]);
|
const pyhistogram& self = bp::extract<const pyhistogram&>(args[0]);
|
||||||
|
|
||||||
const unsigned nargs = bp::len(args) - 1;
|
const unsigned nargs = bp::len(args) - 1;
|
||||||
|
|
||||||
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,84 +359,86 @@ 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string histogram_repr(const pyhistogram &h) {
|
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>>(
|
||||||
.def("__init__", bp::raw_function(histogram_init),
|
"histogram", "N-dimensional histogram for real-valued data.",
|
||||||
":param axis args: axis objects"
|
bp::no_init)
|
||||||
"\nPass one or more axis objects to configure the histogram.")
|
.def("__init__", bp::raw_function(histogram_init),
|
||||||
// shadowed C++ ctors
|
":param axis args: axis objects"
|
||||||
.def(bp::init<const pyhistogram &>())
|
"\nPass one or more axis objects to configure the histogram.")
|
||||||
// .def(bp::init<pyhistogram &&>())
|
// shadowed C++ ctors
|
||||||
|
.def(bp::init<const pyhistogram&>())
|
||||||
|
// .def(bp::init<pyhistogram &&>())
|
||||||
#ifdef HAVE_NUMPY
|
#ifdef HAVE_NUMPY
|
||||||
.add_property("__array_interface__", &bp::access::array_interface)
|
.add_property("__array_interface__", &bp::access::array_interface)
|
||||||
#endif
|
#endif
|
||||||
.add_property("dim", &pyhistogram::dim)
|
.add_property("dim", &pyhistogram::dim)
|
||||||
.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(
|
||||||
":param double args: values (number must match dimension)"
|
"__call__", bp::raw_function(histogram_fill),
|
||||||
"\n:keyword double weight: optional weight"
|
":param double args: values (number must match dimension)"
|
||||||
"\n"
|
"\n:keyword double weight: optional weight"
|
||||||
"\nIf Numpy support is enabled, 1d-arrays can be passed instead of"
|
"\n"
|
||||||
"\nvalues, which must be equal in lenght. Arrays and values can"
|
"\nIf Numpy support is enabled, 1d-arrays can be passed "
|
||||||
"\nbe mixed arbitrarily in the same call.")
|
"instead of"
|
||||||
.def("__len__", &pyhistogram::size,
|
"\nvalues, which must be equal in lenght. Arrays and values can"
|
||||||
":return: total number of bins, including under- and overflow")
|
"\nbe mixed arbitrarily in the same call.")
|
||||||
.def("at", bp::raw_function(histogram_at),
|
.def("__len__", &pyhistogram::size,
|
||||||
":param int args: indices of the bin (number must match dimension)"
|
":return: total number of bins, including under- and overflow")
|
||||||
"\n:return: bin content")
|
.def("at", bp::raw_function(histogram_at),
|
||||||
.def("__getitem__", histogram_getitem,
|
":param int args: indices of the bin (number must match "
|
||||||
":param int args: indices of the bin (number must match dimension)"
|
"dimension)"
|
||||||
"\n:return: bin content")
|
"\n:return: bin content")
|
||||||
.def("reduce_to", bp::raw_function(histogram_reduce_to),
|
.def("__getitem__", histogram_getitem,
|
||||||
":param int args: indices of the axes in the reduced histogram"
|
":param int args: indices of the bin (number must match "
|
||||||
"\n:return: reduced histogram with subset of axes")
|
"dimension)"
|
||||||
.def("__iter__", bp::iterator<pyhistogram>())
|
"\n:return: bin content")
|
||||||
.def("__repr__", histogram_repr,
|
.def("reduce_to", bp::raw_function(histogram_reduce_to),
|
||||||
":return: string representation of the histogram")
|
":param int args: indices of the axes in the reduced histogram"
|
||||||
.def(bp::self == bp::self)
|
"\n:return: reduced histogram with subset of axes")
|
||||||
.def(bp::self != bp::self)
|
.def("__iter__", bp::iterator<pyhistogram>())
|
||||||
.def(bp::self += bp::self)
|
.def("__repr__", histogram_repr,
|
||||||
.def(bp::self *= double())
|
":return: string representation of the histogram")
|
||||||
.def(bp::self * double())
|
.def(bp::self == bp::self)
|
||||||
.def(double() * bp::self)
|
.def(bp::self != bp::self)
|
||||||
.def(bp::self + bp::self)
|
.def(bp::self += bp::self)
|
||||||
.def_pickle(bh::serialization_suite<pyhistogram>())
|
.def(bp::self *= double())
|
||||||
;
|
.def(bp::self * double())
|
||||||
|
.def(double() * bp::self)
|
||||||
|
.def(bp::self + bp::self)
|
||||||
|
.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,10 +5,10 @@
|
|||||||
// 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
|
||||||
|
|
||||||
void register_axis_types();
|
void register_axis_types();
|
||||||
@ -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;
|
||||||
|
@ -31,11 +31,11 @@ namespace detail {
|
|||||||
|
|
||||||
class python_bytes_sink : public iostreams::sink {
|
class python_bytes_sink : public iostreams::sink {
|
||||||
public:
|
public:
|
||||||
python_bytes_sink(PyObject **pstr) : pstr_(pstr), len_(0), pos_(0) {
|
python_bytes_sink(PyObject** pstr) : pstr_(pstr), len_(0), pos_(0) {
|
||||||
BOOST_ASSERT(*pstr == 0);
|
BOOST_ASSERT(*pstr == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::streamsize write(const char *s, std::streamsize n) {
|
std::streamsize write(const char* s, std::streamsize n) {
|
||||||
if (len_ == 0) {
|
if (len_ == 0) {
|
||||||
*pstr_ = PyBytes_FromStringAndSize(s, n);
|
*pstr_ = PyBytes_FromStringAndSize(s, n);
|
||||||
if (*pstr_ == 0) // no point trying to recover from allocation error
|
if (*pstr_ == 0) // no point trying to recover from allocation error
|
||||||
@ -47,7 +47,7 @@ public:
|
|||||||
if (_PyBytes_Resize(pstr_, len_) == -1)
|
if (_PyBytes_Resize(pstr_, len_) == -1)
|
||||||
std::abort(); // no point trying to recover from allocation error
|
std::abort(); // no point trying to recover from allocation error
|
||||||
}
|
}
|
||||||
char *b = PyBytes_AS_STRING(*pstr_);
|
char* b = PyBytes_AS_STRING(*pstr_);
|
||||||
std::copy(s, s + n, b + pos_);
|
std::copy(s, s + n, b + pos_);
|
||||||
}
|
}
|
||||||
pos_ += n;
|
pos_ += n;
|
||||||
@ -55,17 +55,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PyObject **pstr_;
|
PyObject** pstr_;
|
||||||
std::streamsize len_, pos_;
|
std::streamsize len_, pos_;
|
||||||
};
|
};
|
||||||
} // 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);
|
||||||
archive::text_oarchive oa(os);
|
archive::text_oarchive oa(os);
|
||||||
oa << python::extract<const T &>(obj)();
|
oa << python::extract<const T&>(obj)();
|
||||||
os.flush();
|
os.flush();
|
||||||
return python::make_tuple(obj.attr("__dict__"),
|
return python::make_tuple(obj.attr("__dict__"),
|
||||||
python::object(python::handle<>(pobj)));
|
python::object(python::handle<>(pobj)));
|
||||||
@ -81,7 +82,7 @@ template <class T> struct serialization_suite : python::pickle_suite {
|
|||||||
iostreams::stream<iostreams::array_source> is(PyBytes_AS_STRING(o.ptr()),
|
iostreams::stream<iostreams::array_source> is(PyBytes_AS_STRING(o.ptr()),
|
||||||
PyBytes_Size(o.ptr()));
|
PyBytes_Size(o.ptr()));
|
||||||
archive::text_iarchive ia(is);
|
archive::text_iarchive ia(is);
|
||||||
ia >> python::extract<T &>(obj)();
|
ia >> python::extract<T&>(obj)();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool getstate_manages_dict() { return true; }
|
static bool getstate_manages_dict() { return true; }
|
||||||
|
@ -8,22 +8,22 @@
|
|||||||
#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 {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
str dtype_typestr() {
|
str dtype_typestr() {
|
||||||
str s;
|
str s;
|
||||||
if (std::is_floating_point<T>::value)
|
if (std::is_floating_point<T>::value)
|
||||||
s = "|f";
|
s = "|f";
|
||||||
else if (std::is_integral<T>::value)
|
else if (std::is_integral<T>::value)
|
||||||
s = std::is_unsigned<T>::value ? "|u" : "|i";
|
s = std::is_unsigned<T>::value ? "|u" : "|i";
|
||||||
else
|
else
|
||||||
throw std::invalid_argument("T must be a builtin arithmetic type");
|
throw std::invalid_argument("T must be a builtin arithmetic type");
|
||||||
s += str(sizeof(T));
|
s += str(sizeof(T));
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
} // python
|
} // python
|
||||||
} // boost
|
} // boost
|
||||||
|
@ -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,9 +89,9 @@ 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);
|
||||||
auto h2 = make_histogram<array_storage<unsigned>>(
|
auto h2 = make_histogram<array_storage<unsigned>>(
|
||||||
@ -136,8 +136,9 @@ 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 =
|
||||||
array_storage<unsigned>>(h);
|
static_histogram<mp11::mp_list<axis::integer<>, axis::integer<>>,
|
||||||
|
array_storage<unsigned>>(h);
|
||||||
BOOST_TEST_EQ(h3, h);
|
BOOST_TEST_EQ(h3, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,8 +154,9 @@ 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 =
|
||||||
array_storage<unsigned>>();
|
static_histogram<mp11::mp_list<axis::integer<>, axis::integer<>>,
|
||||||
|
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