summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/histogram/examples
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/boost/libs/histogram/examples
parentInitial commit. (diff)
downloadceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz
ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/histogram/examples')
-rw-r--r--src/boost/libs/histogram/examples/Jamfile75
-rw-r--r--src/boost/libs/histogram/examples/getting_started_listing_01.cpp93
-rw-r--r--src/boost/libs/histogram/examples/getting_started_listing_02.cpp83
-rw-r--r--src/boost/libs/histogram/examples/getting_started_listing_03.cpp54
-rw-r--r--src/boost/libs/histogram/examples/getting_started_listing_04.cpp60
-rw-r--r--src/boost/libs/histogram/examples/getting_started_listing_05.cpp65
-rw-r--r--src/boost/libs/histogram/examples/guide_axis_basic_demo.cpp82
-rw-r--r--src/boost/libs/histogram/examples/guide_axis_circular.cpp43
-rw-r--r--src/boost/libs/histogram/examples/guide_axis_growing.cpp62
-rw-r--r--src/boost/libs/histogram/examples/guide_axis_with_labels.cpp21
-rw-r--r--src/boost/libs/histogram/examples/guide_axis_with_transform.cpp57
-rw-r--r--src/boost/libs/histogram/examples/guide_axis_with_uoflow_off.cpp30
-rw-r--r--src/boost/libs/histogram/examples/guide_custom_2d_axis.cpp56
-rw-r--r--src/boost/libs/histogram/examples/guide_custom_accumulators_advanced.cpp52
-rw-r--r--src/boost/libs/histogram/examples/guide_custom_accumulators_builtin.cpp43
-rw-r--r--src/boost/libs/histogram/examples/guide_custom_accumulators_ouroboros.cpp51
-rw-r--r--src/boost/libs/histogram/examples/guide_custom_accumulators_simple.cpp44
-rw-r--r--src/boost/libs/histogram/examples/guide_custom_accumulators_with_metadata.cpp47
-rw-r--r--src/boost/libs/histogram/examples/guide_custom_minimal_axis.cpp41
-rw-r--r--src/boost/libs/histogram/examples/guide_custom_modified_axis.cpp47
-rw-r--r--src/boost/libs/histogram/examples/guide_custom_storage.cpp47
-rw-r--r--src/boost/libs/histogram/examples/guide_fill_histogram.cpp61
-rw-r--r--src/boost/libs/histogram/examples/guide_fill_profile.cpp53
-rw-r--r--src/boost/libs/histogram/examples/guide_fill_weighted_histogram.cpp36
-rw-r--r--src/boost/libs/histogram/examples/guide_fill_weighted_profile.cpp51
-rw-r--r--src/boost/libs/histogram/examples/guide_histogram_in_api.cpp57
-rw-r--r--src/boost/libs/histogram/examples/guide_histogram_operators.cpp62
-rw-r--r--src/boost/libs/histogram/examples/guide_histogram_projection.cpp58
-rw-r--r--src/boost/libs/histogram/examples/guide_histogram_reduction.cpp48
-rw-r--r--src/boost/libs/histogram/examples/guide_histogram_serialization.cpp47
-rw-r--r--src/boost/libs/histogram/examples/guide_histogram_streaming.cpp62
-rw-r--r--src/boost/libs/histogram/examples/guide_indexed_access.cpp78
-rw-r--r--src/boost/libs/histogram/examples/guide_make_dynamic_histogram.cpp47
-rw-r--r--src/boost/libs/histogram/examples/guide_make_static_histogram.cpp23
-rw-r--r--src/boost/libs/histogram/examples/guide_parallel_filling.cpp50
-rw-r--r--src/boost/libs/histogram/examples/guide_stdlib_algorithms.cpp67
36 files changed, 1953 insertions, 0 deletions
diff --git a/src/boost/libs/histogram/examples/Jamfile b/src/boost/libs/histogram/examples/Jamfile
new file mode 100644
index 000000000..e1b85e0e7
--- /dev/null
+++ b/src/boost/libs/histogram/examples/Jamfile
@@ -0,0 +1,75 @@
+# Copyright (c) 2018 Mateusz Loskot <mateusz@loskot.net>
+# Copyright (c) 2019 Hans Dembinski
+#
+# Use, modification and distribution is subject to the Boost Software License,
+# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import testing ;
+import ../../config/checks/config : requires ;
+
+project
+ : requirements
+ [ requires
+ cxx14_constexpr cxx14_decltype_auto cxx14_generic_lambdas cxx14_return_type_deduction cxx11_user_defined_literals
+ # list could go on...
+ ]
+ ;
+
+alias cxx14 :
+ [ run getting_started_listing_01.cpp ]
+ [ run getting_started_listing_02.cpp ]
+ [ run getting_started_listing_03.cpp ]
+ [ run getting_started_listing_04.cpp ]
+ [ run getting_started_listing_05.cpp ]
+ [ run guide_axis_basic_demo.cpp ]
+ [ run guide_axis_circular.cpp ]
+ [ run guide_axis_growing.cpp ]
+ [ run guide_axis_with_labels.cpp ]
+ [ run guide_axis_with_transform.cpp ]
+ [ run guide_axis_with_uoflow_off.cpp ]
+ [ run guide_custom_2d_axis.cpp ]
+ [ run guide_custom_accumulators_builtin.cpp ]
+ [ run guide_custom_accumulators_with_metadata.cpp ]
+ [ run guide_custom_accumulators_simple.cpp ]
+ [ run guide_custom_accumulators_advanced.cpp ]
+ [ run guide_custom_accumulators_ouroboros.cpp ]
+ [ run guide_custom_minimal_axis.cpp ]
+ [ run guide_custom_modified_axis.cpp ]
+ [ run guide_custom_storage.cpp ]
+ [ run guide_fill_histogram.cpp ]
+ [ run guide_fill_profile.cpp ]
+ [ run guide_fill_weighted_histogram.cpp ]
+ [ run guide_fill_weighted_profile.cpp ]
+ [ run guide_histogram_operators.cpp ]
+ [ run guide_histogram_reduction.cpp ]
+ [ run guide_histogram_projection.cpp ]
+ [ run guide_histogram_streaming.cpp ]
+ [ run guide_histogram_in_api.cpp ]
+ [ run guide_indexed_access.cpp ]
+ [ run guide_make_dynamic_histogram.cpp ]
+ [ run guide_make_static_histogram.cpp ]
+ [ run guide_stdlib_algorithms.cpp ]
+ ;
+
+alias threading :
+ [ run guide_parallel_filling.cpp ] :
+ <threading>multi
+ ;
+
+alias libserial :
+ /boost/serialization//boost_serialization :
+ <link>static <warnings>off <rtti>on
+ ;
+
+alias serial :
+ [ run guide_histogram_serialization.cpp libserial ] :
+ <warnings>off
+ ;
+
+alias all : cxx14 threading serial ;
+
+explicit cxx14 ;
+explicit threading ;
+explicit libserial ;
+explicit serial ;
diff --git a/src/boost/libs/histogram/examples/getting_started_listing_01.cpp b/src/boost/libs/histogram/examples/getting_started_listing_01.cpp
new file mode 100644
index 000000000..a83df68d7
--- /dev/null
+++ b/src/boost/libs/histogram/examples/getting_started_listing_01.cpp
@@ -0,0 +1,93 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// clang-format off
+
+//[ getting_started_listing_01
+
+#include <algorithm> // std::for_each
+#include <boost/format.hpp> // only needed for printing
+#include <boost/histogram.hpp> // make_histogram, regular, weight, indexed
+#include <cassert> // assert (used to test this example for correctness)
+#include <functional> // std::ref
+#include <iostream> // std::cout, std::flush
+#include <sstream> // std::ostringstream
+
+int main() {
+ using namespace boost::histogram; // strip the boost::histogram prefix
+
+ /*
+ Create a 1d-histogram with a regular axis that has 6 equidistant bins on
+ the real line from -1.0 to 2.0, and label it as "x". A family of overloaded
+ factory functions called `make_histogram` makes creating histograms easy.
+
+ A regular axis is a sequence of semi-open bins. Extra under- and overflow
+ bins extend the axis by default (this can be turned off).
+
+ index : -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6
+ bin edges: -inf -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 inf
+ */
+ auto h = make_histogram(axis::regular<>(6, -1.0, 2.0, "x"));
+
+ /*
+ Let's fill a histogram with data, typically this happens in a loop.
+
+ STL algorithms are supported. std::for_each is very convenient to fill a
+ histogram from an iterator range. Use std::ref in the call, if you don't
+ want std::for_each to make a copy of your histogram.
+ */
+ auto data = {-0.5, 1.1, 0.3, 1.7};
+ std::for_each(data.begin(), data.end(), std::ref(h));
+ // let's fill some more values manually
+ h(-1.5); // is placed in underflow bin -1
+ h(-1.0); // is placed in bin 0, bin interval is semi-open
+ h(2.0); // is placed in overflow bin 6, bin interval is semi-open
+ h(20.0); // is placed in overflow bin 6
+
+ /*
+ This does a weighted fill using the `weight` function as an additional
+ argument. It may appear at the beginning or end of the argument list. C++
+ doesn't have keyword arguments like Python, this is the next-best thing.
+ */
+ h(0.1, weight(1.0));
+
+ /*
+ Iterate over bins with the `indexed` range generator, which provides a
+ special accessor object, that can be used to obtain the current bin index,
+ and the current bin value by dereferncing (it acts like a pointer to the
+ value). Using `indexed` is convenient and gives you better performance than
+ looping over the histogram cells with hand-written for loops. By default,
+ under- and overflow bins are skipped. Passing `coverage::all` as the
+ optional second argument iterates over all bins.
+
+ - Access the value with the dereference operator.
+ - Access the current index with `index(d)` method of the accessor.
+ - Access the corresponding bin interval view with `bin(d)`.
+
+ The return type of `bin(d)` depends on the axis type (see the axis reference
+ for details). It usually is a class that represents a semi-open interval.
+ Edges can be accessed with methods `lower()` and `upper()`.
+ */
+
+ std::ostringstream os;
+ for (auto&& x : indexed(h, coverage::all)) {
+ os << boost::format("bin %2i [%4.1f, %4.1f): %i\n")
+ % x.index() % x.bin().lower() % x.bin().upper() % *x;
+ }
+
+ std::cout << os.str() << std::flush;
+
+ assert(os.str() == "bin -1 [-inf, -1.0): 1\n"
+ "bin 0 [-1.0, -0.5): 1\n"
+ "bin 1 [-0.5, -0.0): 1\n"
+ "bin 2 [-0.0, 0.5): 2\n"
+ "bin 3 [ 0.5, 1.0): 0\n"
+ "bin 4 [ 1.0, 1.5): 1\n"
+ "bin 5 [ 1.5, 2.0): 1\n"
+ "bin 6 [ 2.0, inf): 2\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/getting_started_listing_02.cpp b/src/boost/libs/histogram/examples/getting_started_listing_02.cpp
new file mode 100644
index 000000000..cf5b3143a
--- /dev/null
+++ b/src/boost/libs/histogram/examples/getting_started_listing_02.cpp
@@ -0,0 +1,83 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// clang-format off
+
+//[ getting_started_listing_02
+
+#include <boost/format.hpp>
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+int main() {
+ using namespace boost::histogram;
+
+ /*
+ Create a histogram which can be configured dynamically at run-time. The axis
+ configuration is first collected in a vector of axis::variant type, which
+ can hold different axis types (those in its template argument list). Here,
+ we use a variant that can store a regular and a category axis.
+ */
+ using reg = axis::regular<>;
+ using cat = axis::category<std::string>;
+ using variant = axis::variant<axis::regular<>, axis::category<std::string>>;
+ std::vector<variant> axes;
+ axes.emplace_back(cat({"red", "blue"}));
+ axes.emplace_back(reg(3, 0.0, 1.0, "x"));
+ axes.emplace_back(reg(3, 0.0, 1.0, "y"));
+ // passing an iterator range also works here
+ auto h = make_histogram(std::move(axes));
+
+ // fill histogram with data, usually this happens in a loop
+ h("red", 0.1, 0.2);
+ h("blue", 0.7, 0.3);
+ h("red", 0.3, 0.7);
+ h("red", 0.7, 0.7);
+
+ /*
+ Print histogram by iterating over bins.
+ Since the [bin type] of the category axis cannot be converted into a double,
+ it cannot be handled by the polymorphic interface of axis::variant. We use
+ axis::get to "cast" the variant type to the actual category type.
+ */
+
+ // get reference to category axis, performs a run-time checked static cast
+ const auto& cat_axis = axis::get<cat>(h.axis(0));
+ std::ostringstream os;
+ for (auto&& x : indexed(h)) {
+ os << boost::format("(%i, %i, %i) %4s [%3.1f, %3.1f) [%3.1f, %3.1f) %3.0f\n")
+ % x.index(0) % x.index(1) % x.index(2)
+ % cat_axis.bin(x.index(0))
+ % x.bin(1).lower() % x.bin(1).upper()
+ % x.bin(2).lower() % x.bin(2).upper()
+ % *x;
+ }
+
+ std::cout << os.str() << std::flush;
+ assert(os.str() == "(0, 0, 0) red [0.0, 0.3) [0.0, 0.3) 1\n"
+ "(1, 0, 0) blue [0.0, 0.3) [0.0, 0.3) 0\n"
+ "(0, 1, 0) red [0.3, 0.7) [0.0, 0.3) 0\n"
+ "(1, 1, 0) blue [0.3, 0.7) [0.0, 0.3) 0\n"
+ "(0, 2, 0) red [0.7, 1.0) [0.0, 0.3) 0\n"
+ "(1, 2, 0) blue [0.7, 1.0) [0.0, 0.3) 1\n"
+ "(0, 0, 1) red [0.0, 0.3) [0.3, 0.7) 0\n"
+ "(1, 0, 1) blue [0.0, 0.3) [0.3, 0.7) 0\n"
+ "(0, 1, 1) red [0.3, 0.7) [0.3, 0.7) 0\n"
+ "(1, 1, 1) blue [0.3, 0.7) [0.3, 0.7) 0\n"
+ "(0, 2, 1) red [0.7, 1.0) [0.3, 0.7) 0\n"
+ "(1, 2, 1) blue [0.7, 1.0) [0.3, 0.7) 0\n"
+ "(0, 0, 2) red [0.0, 0.3) [0.7, 1.0) 1\n"
+ "(1, 0, 2) blue [0.0, 0.3) [0.7, 1.0) 0\n"
+ "(0, 1, 2) red [0.3, 0.7) [0.7, 1.0) 0\n"
+ "(1, 1, 2) blue [0.3, 0.7) [0.7, 1.0) 0\n"
+ "(0, 2, 2) red [0.7, 1.0) [0.7, 1.0) 1\n"
+ "(1, 2, 2) blue [0.7, 1.0) [0.7, 1.0) 0\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/getting_started_listing_03.cpp b/src/boost/libs/histogram/examples/getting_started_listing_03.cpp
new file mode 100644
index 000000000..f3ebfcd8c
--- /dev/null
+++ b/src/boost/libs/histogram/examples/getting_started_listing_03.cpp
@@ -0,0 +1,54 @@
+// Copyright 2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// clang-format off
+
+//[ getting_started_listing_03
+
+#include <boost/format.hpp>
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+
+int main() {
+ using namespace boost::histogram;
+
+ /*
+ Create a profile. Profiles does not only count entries in each cell, but
+ also compute the mean of a sample value in each cell.
+ */
+ auto p = make_profile(axis::regular<>(5, 0.0, 1.0));
+
+ /*
+ Fill profile with data, usually this happens in a loop. You pass the sample
+ with the `sample` helper function. The sample can be the first or last
+ argument.
+ */
+ p(0.1, sample(1));
+ p(0.15, sample(3));
+ p(0.2, sample(4));
+ p(0.9, sample(5));
+
+ /*
+ Iterate over bins and print profile.
+ */
+ std::ostringstream os;
+ for (auto&& x : indexed(p)) {
+ os << boost::format("bin %i [%3.1f, %3.1f) count %i mean %g\n")
+ % x.index() % x.bin().lower() % x.bin().upper()
+ % x->count() % x->value();
+ }
+
+ std::cout << os.str() << std::flush;
+ assert(os.str() == "bin 0 [0.0, 0.2) count 2 mean 2\n"
+ "bin 1 [0.2, 0.4) count 1 mean 4\n"
+ "bin 2 [0.4, 0.6) count 0 mean 0\n"
+ "bin 3 [0.6, 0.8) count 0 mean 0\n"
+ "bin 4 [0.8, 1.0) count 1 mean 5\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/getting_started_listing_04.cpp b/src/boost/libs/histogram/examples/getting_started_listing_04.cpp
new file mode 100644
index 000000000..fe44b1f51
--- /dev/null
+++ b/src/boost/libs/histogram/examples/getting_started_listing_04.cpp
@@ -0,0 +1,60 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// clang-format off
+
+//[ getting_started_listing_04
+
+#include <algorithm> // std::max_element
+#include <boost/format.hpp> // only needed for printing
+#include <boost/histogram.hpp> // make_histogram, integer, indexed
+#include <iostream> // std::cout, std::endl
+#include <sstream> // std::ostringstream
+
+int main() {
+ using namespace boost::histogram;
+ using namespace boost::histogram::literals;
+
+ /*
+ We make a 3d histogram for color values (r, g, b) in an image. We assume the values
+ are of type char. The value range then is [0, 256). The integer axis is perfect for
+ color values.
+ */
+ auto h = make_histogram(
+ axis::integer<>(0, 256, "r"),
+ axis::integer<>(0, 256, "g"),
+ axis::integer<>(0, 256, "b")
+ );
+
+ /*
+ We don't have real image data, so fill some fake data.
+ */
+ h(1, 2, 3);
+ h(1, 2, 3);
+ h(0, 1, 0);
+
+ /*
+ Now let's say we want to know which color is most common. We can use std::max_element
+ on an indexed range for that.
+ */
+ auto ind = indexed(h);
+ auto max_it = std::max_element(ind.begin(), ind.end());
+
+ /*
+ max_it is a special iterator to the histogram cell with the highest count.
+ This iterator allows one to access the cell value, bin indices, and bin values.
+ You need to twice dereference it to get to the cell value.
+ */
+ std::ostringstream os;
+ os << boost::format("count=%i rgb=(%i, %i, %i)")
+ % **max_it % max_it->bin(0_c) % max_it->bin(1) % max_it->bin(2);
+
+ std::cout << os.str() << std::endl;
+
+ assert(os.str() == "count=2 rgb=(1, 2, 3)");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/getting_started_listing_05.cpp b/src/boost/libs/histogram/examples/getting_started_listing_05.cpp
new file mode 100644
index 000000000..52706284b
--- /dev/null
+++ b/src/boost/libs/histogram/examples/getting_started_listing_05.cpp
@@ -0,0 +1,65 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// clang-format off
+
+//[ getting_started_listing_05
+
+//////////////// Begin: put this in header file ////////////////////
+
+#include <algorithm> // std::max_element
+#include <boost/format.hpp> // only needed for printing
+#include <boost/histogram.hpp> // make_histogram, integer, indexed
+#include <iostream> // std::cout, std::endl
+#include <sstream> // std::ostringstream
+#include <tuple>
+#include <vector>
+
+// use this when axis configuration is fix to get highest performance
+struct HolderOfStaticHistogram {
+ // put axis types here
+ using axes_t = std::tuple<
+ boost::histogram::axis::regular<>,
+ boost::histogram::axis::integer<>
+ >;
+ using hist_t = boost::histogram::histogram<axes_t>;
+ hist_t hist_;
+};
+
+// use this when axis configuration should be flexible
+struct HolderOfDynamicHistogram {
+ // put all axis types here that you are going to use
+ using axis_t = boost::histogram::axis::variant<
+ boost::histogram::axis::regular<>,
+ boost::histogram::axis::variable<>,
+ boost::histogram::axis::integer<>
+ >;
+ using axes_t = std::vector<axis_t>;
+ using hist_t = boost::histogram::histogram<axes_t>;
+ hist_t hist_;
+};
+
+//////////////// End: put this in header file ////////////////////
+
+int main() {
+ using namespace boost::histogram;
+
+ HolderOfStaticHistogram hs;
+ hs.hist_ = make_histogram(axis::regular<>(5, 0, 1), axis::integer<>(0, 3));
+ // now assign a different histogram
+ hs.hist_ = make_histogram(axis::regular<>(3, 1, 2), axis::integer<>(4, 6));
+ // hs.hist_ = make_histogram(axis::regular<>(5, 0, 1)); does not work;
+ // the static histogram cannot change the number or order of axis types
+
+ HolderOfDynamicHistogram hd;
+ hd.hist_ = make_histogram(axis::regular<>(5, 0, 1), axis::integer<>(0, 3));
+ // now assign a different histogram
+ hd.hist_ = make_histogram(axis::regular<>(3, -1, 2));
+ // and assign another
+ hd.hist_ = make_histogram(axis::integer<>(0, 5), axis::integer<>(3, 5));
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_axis_basic_demo.cpp b/src/boost/libs/histogram/examples/guide_axis_basic_demo.cpp
new file mode 100644
index 000000000..2612d043c
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_axis_basic_demo.cpp
@@ -0,0 +1,82 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_axis_basic_demo
+
+#include <boost/histogram/axis.hpp>
+#include <limits>
+
+int main() {
+ using namespace boost::histogram;
+
+ // make a regular axis with 10 bins over interval from 1.5 to 2.5
+ auto r = axis::regular<>{10, 1.5, 2.5};
+ // `<>` is needed in C++14 because the axis is templated,
+ // in C++17 you can do: auto r = axis::regular{10, 1.5, 2.5};
+ assert(r.size() == 10);
+ // alternatively, you can define the step size with the `step` marker
+ auto r_step = axis::regular<>{axis::step(0.1), 1.5, 2.5};
+ assert(r_step == r);
+
+ // histogram uses the `index` method to convert values to indices
+ // note: intervals of builtin axis types are always semi-open [a, b)
+ assert(r.index(1.5) == 0);
+ assert(r.index(1.6) == 1);
+ assert(r.index(2.4) == 9);
+ // index for a value below the start of the axis is always -1
+ assert(r.index(1.0) == -1);
+ assert(r.index(-std::numeric_limits<double>::infinity()) == -1);
+ // index for a value below the above the end of the axis is always `size()`
+ assert(r.index(3.0) == 10);
+ assert(r.index(std::numeric_limits<double>::infinity()) == 10);
+ // index for not-a-number is also `size()` by convention
+ assert(r.index(std::numeric_limits<double>::quiet_NaN()) == 10);
+
+ // make a variable axis with 3 bins [-1.5, 0.1), [0.1, 0.3), [0.3, 10)
+ auto v = axis::variable<>{-1.5, 0.1, 0.3, 10.};
+ assert(v.index(-2.0) == -1);
+ assert(v.index(-1.5) == 0);
+ assert(v.index(0.1) == 1);
+ assert(v.index(0.3) == 2);
+ assert(v.index(10) == 3);
+ assert(v.index(20) == 3);
+
+ // make an integer axis with 3 bins at -1, 0, 1
+ auto i = axis::integer<>{-1, 2};
+ assert(i.index(-2) == -1);
+ assert(i.index(-1) == 0);
+ assert(i.index(0) == 1);
+ assert(i.index(1) == 2);
+ assert(i.index(2) == 3);
+
+ // make an integer axis called "foo"
+ auto i_with_label = axis::integer<>{-1, 2, "foo"};
+ // all builtin axis types allow you to pass some optional metadata as the last
+ // argument in the constructor; a string by default, but can be any copyable type
+
+ // two axis do not compare equal if they differ in their metadata
+ assert(i != i_with_label);
+
+ // integer axis also work well with unscoped enums
+ enum { red, blue };
+ auto i_for_enum = axis::integer<>{red, blue + 1};
+ assert(i_for_enum.index(red) == 0);
+ assert(i_for_enum.index(blue) == 1);
+
+ // make a category axis from a scoped enum and/or if the identifiers are not consecutive
+ enum class Bar { red = 12, blue = 6 };
+ auto c = axis::category<Bar>{Bar::red, Bar::blue};
+ assert(c.index(Bar::red) == 0);
+ assert(c.index(Bar::blue) == 1);
+ // c.index(12) is a compile-time error, since the argument must be of type `Bar`
+
+ // category axis can be created for any copyable and equal-comparable type
+ auto c_str = axis::category<std::string>{"red", "blue"};
+ assert(c_str.index("red") == 0);
+ assert(c_str.index("blue") == 1);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_axis_circular.cpp b/src/boost/libs/histogram/examples/guide_axis_circular.cpp
new file mode 100644
index 000000000..b4b8b4941
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_axis_circular.cpp
@@ -0,0 +1,43 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_axis_circular
+
+#include <boost/histogram/axis.hpp>
+#include <limits>
+
+int main() {
+ using namespace boost::histogram;
+
+ // make a circular regular axis ... [0, 180), [180, 360), [0, 180) ....
+ using opts = decltype(axis::option::overflow | axis::option::circular);
+ auto r = axis::regular<double, use_default, use_default, opts>{2, 0., 360.};
+ assert(r.index(-180) == 1);
+ assert(r.index(0) == 0);
+ assert(r.index(180) == 1);
+ assert(r.index(360) == 0);
+ assert(r.index(540) == 1);
+ assert(r.index(720) == 0);
+ // special values are mapped to the overflow bin index
+ assert(r.index(std::numeric_limits<double>::infinity()) == 2);
+ assert(r.index(-std::numeric_limits<double>::infinity()) == 2);
+ assert(r.index(std::numeric_limits<double>::quiet_NaN()) == 2);
+
+ // since the regular axis is the most common circular axis, there exists an alias
+ auto c = axis::circular<>{2, 0., 360.};
+ assert(r == c);
+
+ // make a circular integer axis
+ auto i = axis::integer<int, use_default, axis::option::circular_t>{1, 4};
+ assert(i.index(0) == 2);
+ assert(i.index(1) == 0);
+ assert(i.index(2) == 1);
+ assert(i.index(3) == 2);
+ assert(i.index(4) == 0);
+ assert(i.index(5) == 1);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_axis_growing.cpp b/src/boost/libs/histogram/examples/guide_axis_growing.cpp
new file mode 100644
index 000000000..5aed481b3
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_axis_growing.cpp
@@ -0,0 +1,62 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// clang-format off
+
+//[ guide_axis_growing
+
+#include <boost/histogram.hpp>
+#include <cassert>
+
+#include <iostream>
+
+int main() {
+ using namespace boost::histogram;
+
+ // make a growing regular axis
+ // - it grows new bins with its constant bin width until the value is covered
+ auto h1 = make_histogram(axis::regular<double,
+ use_default,
+ use_default,
+ axis::option::growth_t>{2, 0., 1.});
+ // nothing special happens here
+ h1(0.1);
+ h1(0.9);
+ // state: [0, 0.5): 1, [0.5, 1.0): 1
+ assert(h1.axis().size() == 2);
+ assert(h1.axis().bin(0).lower() == 0.0);
+ assert(h1.axis().bin(1).upper() == 1.0);
+
+ // value below range: axis grows new bins until value is in range
+ h1(-0.3);
+ // state: [-0.5, 0.0): 1, [0, 0.5): 1, [0.5, 1.0): 1
+ assert(h1.axis().size() == 3);
+ assert(h1.axis().bin(0).lower() == -0.5);
+ assert(h1.axis().bin(2).upper() == 1.0);
+
+ h1(1.9);
+ // state: [-0.5, 0.0): 1, [0, 0.5): 1, [0.5, 1.0): 1, [1.0, 1.5): 0 [1.5, 2.0): 1
+ assert(h1.axis().size() == 5);
+ assert(h1.axis().bin(0).lower() == -0.5);
+ assert(h1.axis().bin(4).upper() == 2.0);
+
+ // make a growing category axis (here strings)
+ // - empty axis is allowed: very useful if categories are not known at the beginning
+ auto h2 = make_histogram(axis::category<std::string,
+ use_default,
+ axis::option::growth_t>());
+ assert(h2.size() == 0); // histogram is empty
+ h2("foo"); // new bin foo, index 0
+ assert(h2.size() == 1);
+ h2("bar"); // new bin bar, index 1
+ assert(h2.size() == 2);
+ h2("foo");
+ assert(h2.size() == 2);
+ assert(h2[0] == 2);
+ assert(h2[1] == 1);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_axis_with_labels.cpp b/src/boost/libs/histogram/examples/guide_axis_with_labels.cpp
new file mode 100644
index 000000000..3f3ad8b54
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_axis_with_labels.cpp
@@ -0,0 +1,21 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_axis_with_labels
+
+#include <boost/histogram.hpp>
+
+int main() {
+ using namespace boost::histogram;
+
+ // create a 2d-histogram with an "age" and an "income" axis
+ auto h = make_histogram(axis::regular<>(20, 0.0, 100.0, "age in years"),
+ axis::regular<>(20, 0.0, 100.0, "yearly income in Thousands"));
+
+ // do something with h
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_axis_with_transform.cpp b/src/boost/libs/histogram/examples/guide_axis_with_transform.cpp
new file mode 100644
index 000000000..9b3412a7c
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_axis_with_transform.cpp
@@ -0,0 +1,57 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_axis_with_transform
+
+#include <boost/histogram/axis/regular.hpp>
+#include <limits>
+
+int main() {
+ using namespace boost::histogram;
+
+ // make a regular axis with a log transform over [10, 100), [100, 1000), [1000, 10000)
+ axis::regular<double, axis::transform::log> r_log{3, 10., 10000.};
+ // log transform:
+ // - useful when values vary dramatically in magnitude, like brightness of stars
+ // - edges are not exactly at 10, 100, 1000, because of finite floating point precision
+ // - values >= 0 but smaller than the starting value of the axis are mapped to -1
+ // - values < 0 are mapped to `size()`, because the result of std::log(value) is NaN
+ assert(r_log.index(10.1) == 0);
+ assert(r_log.index(100.1) == 1);
+ assert(r_log.index(1000.1) == 2);
+ assert(r_log.index(1) == -1);
+ assert(r_log.index(0) == -1);
+ assert(r_log.index(-1) == 3);
+
+ // make a regular axis with a sqrt transform over [4, 9), [9, 16), [16, 25)
+ axis::regular<double, axis::transform::sqrt> r_sqrt{3, 4., 25.};
+ // sqrt transform:
+ // - bin widths are more mildly increasing compared to log transform
+ // - axis starting at value == 0 is ok, sqrt(0) == 0 unlike log transform
+ // - values < 0 are mapped to `size()`, because the result of std::sqrt(value) is NaN
+ assert(r_sqrt.index(0) == -1);
+ assert(r_sqrt.index(4.1) == 0);
+ assert(r_sqrt.index(9.1) == 1);
+ assert(r_sqrt.index(16.1) == 2);
+ assert(r_sqrt.index(25.1) == 3);
+ assert(r_sqrt.index(-1) == 3);
+
+ // make a regular axis with a power transform x^1/3 over [1, 8), [8, 27), [27, 64)
+ using pow_trans = axis::transform::pow;
+ axis::regular<double, pow_trans> r_pow(pow_trans{1. / 3.}, 3, 1., 64.);
+ // pow transform:
+ // - generalization of the sqrt transform
+ // - starting the axis at value == 0 is ok for power p > 0, 0^p == 0 for p > 0
+ // - values < 0 are mapped to `size()` if power p is not a positive integer
+ assert(r_pow.index(0) == -1);
+ assert(r_pow.index(1.1) == 0);
+ assert(r_pow.index(8.1) == 1);
+ assert(r_pow.index(27.1) == 2);
+ assert(r_pow.index(64.1) == 3);
+ assert(r_pow.index(-1) == 3);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_axis_with_uoflow_off.cpp b/src/boost/libs/histogram/examples/guide_axis_with_uoflow_off.cpp
new file mode 100644
index 000000000..7fe96f5d7
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_axis_with_uoflow_off.cpp
@@ -0,0 +1,30 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_axis_with_uoflow_off
+
+#include <boost/histogram.hpp>
+#include <string>
+
+int main() {
+ using namespace boost::histogram;
+
+ // create a 1d-histogram over integer values from 1 to 6
+ auto h1 = make_histogram(axis::integer<int>(1, 7));
+ // axis has size 6...
+ assert(h1.axis().size() == 6);
+ // ... but histogram has size 8, because of overflow and underflow bins
+ assert(h1.size() == 8);
+
+ // create a 1d-histogram for throws of a six-sided die without extra bins,
+ // since the values cannot be smaller than 1 or larger than 6
+ auto h2 = make_histogram(axis::integer<int, use_default, axis::option::none_t>(1, 7));
+ // now size of axis and histogram is equal
+ assert(h2.axis().size() == 6);
+ assert(h2.size() == 6);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_custom_2d_axis.cpp b/src/boost/libs/histogram/examples/guide_custom_2d_axis.cpp
new file mode 100644
index 000000000..6a952a659
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_custom_2d_axis.cpp
@@ -0,0 +1,56 @@
+// Copyright 2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_custom_2d_axis
+
+#include <boost/histogram.hpp>
+#include <cassert>
+
+int main() {
+ using namespace boost::histogram;
+
+ // axis which returns 1 if the input falls inside the unit circle and zero otherwise
+ struct circle_axis {
+ // accepts a 2D point in form of a std::tuple
+ axis::index_type index(const std::tuple<double, double>& point) const {
+ const auto x = std::get<0>(point);
+ const auto y = std::get<1>(point);
+ return x * x + y * y <= 1.0;
+ }
+
+ axis::index_type size() const { return 2; }
+ };
+
+ auto h1 = make_histogram(circle_axis());
+
+ // fill looks normal for a histogram which has only one Nd-axis
+ h1(0, 0); // in
+ h1(0, -1); // in
+ h1(0, 1); // in
+ h1(-1, 0); // in
+ h1(1, 0); // in
+ h1(1, 1); // out
+ h1(-1, -1); // out
+
+ // 2D histogram, but only 1D index
+ assert(h1.at(0) == 2); // out
+ assert(h1.at(1) == 5); // in
+
+ // other axes can be combined with a Nd-axis
+ auto h2 = make_histogram(circle_axis(), axis::category<std::string>({"red", "blue"}));
+
+ // now we need to pass arguments for Nd-axis explicitly as std::tuple
+ h2(std::make_tuple(0, 0), "red");
+ h2(std::make_tuple(1, 1), "blue");
+
+ // 3D histogram, but only 2D index
+ assert(h2.at(0, 0) == 0); // out, red
+ assert(h2.at(0, 1) == 1); // out, blue
+ assert(h2.at(1, 0) == 1); // in, red
+ assert(h2.at(1, 1) == 0); // in, blue
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_custom_accumulators_advanced.cpp b/src/boost/libs/histogram/examples/guide_custom_accumulators_advanced.cpp
new file mode 100644
index 000000000..16ab559f2
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_custom_accumulators_advanced.cpp
@@ -0,0 +1,52 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_custom_accumulators_advanced
+
+#include <boost/format.hpp>
+#include <boost/histogram.hpp>
+#include <iostream>
+#include <sstream>
+
+int main() {
+ using namespace boost::histogram;
+
+ // Accumulator accepts two samples and an optional weight and computes the mean of each.
+ struct multi_mean {
+ accumulators::mean<> mx, my;
+
+ // called when no weight is passed
+ void operator()(double x, double y) {
+ mx(x);
+ my(y);
+ }
+
+ // called when a weight is passed
+ void operator()(weight_type<double> w, double x, double y) {
+ mx(w, x);
+ my(w, y);
+ }
+ };
+ // Note: The implementation can be made more efficient by sharing the sum of weights.
+
+ // Create a 1D histogram that uses the custom accumulator.
+ auto h = make_histogram_with(dense_storage<multi_mean>(), axis::integer<>(0, 2));
+ h(0, sample(1, 2)); // samples go to first cell
+ h(0, sample(3, 4)); // samples go to first cell
+ h(1, sample(5, 6), weight(2)); // samples go to second cell
+ h(1, sample(7, 8), weight(3)); // samples go to second cell
+
+ std::ostringstream os;
+ for (auto&& bin : indexed(h)) {
+ os << boost::format("index %i mean-x %.1f mean-y %.1f\n") % bin.index() %
+ bin->mx.value() % bin->my.value();
+ }
+ std::cout << os.str() << std::flush;
+ assert(os.str() == "index 0 mean-x 2.0 mean-y 3.0\n"
+ "index 1 mean-x 6.2 mean-y 7.2\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_custom_accumulators_builtin.cpp b/src/boost/libs/histogram/examples/guide_custom_accumulators_builtin.cpp
new file mode 100644
index 000000000..59c1e1c7a
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_custom_accumulators_builtin.cpp
@@ -0,0 +1,43 @@
+// Copyright 2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_custom_accumulators_builtin
+
+#include <boost/format.hpp>
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+
+int main() {
+ using namespace boost::histogram;
+ using mean = accumulators::mean<>;
+
+ // Create a 1D-profile, which computes the mean of samples in each bin.
+ auto h = make_histogram_with(dense_storage<mean>(), axis::integer<>(0, 2));
+ // The factory function `make_profile` is provided as a shorthand for this, so this is
+ // equivalent to the previous line: auto h = make_profile(axis::integer<>(0, 2));
+
+ // An argument marked as `sample` is passed to the accumulator.
+ h(0, sample(1)); // sample goes to first cell
+ h(0, sample(2)); // sample goes to first cell
+ h(1, sample(3)); // sample goes to second cell
+ h(1, sample(4)); // sample goes to second cell
+
+ std::ostringstream os;
+ for (auto&& x : indexed(h)) {
+ // Accumulators usually have methods to access their state. Use the arrow
+ // operator to access them. Here, `count()` gives the number of samples,
+ // `value()` the mean, and `variance()` the variance estimate of the mean.
+ os << boost::format("index %i count %i mean %.1f variance %.1f\n") % x.index() %
+ x->count() % x->value() % x->variance();
+ }
+ std::cout << os.str() << std::flush;
+ assert(os.str() == "index 0 count 2 mean 1.5 variance 0.5\n"
+ "index 1 count 2 mean 3.5 variance 0.5\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_custom_accumulators_ouroboros.cpp b/src/boost/libs/histogram/examples/guide_custom_accumulators_ouroboros.cpp
new file mode 100644
index 000000000..5d7299e18
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_custom_accumulators_ouroboros.cpp
@@ -0,0 +1,51 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_custom_accumulators_ouroboros
+
+#include <boost/histogram.hpp>
+#include <cmath>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+int main() {
+ using namespace boost::histogram;
+
+ // First we define the nested histogram type.
+ using axis_t = axis::category<int, axis::null_type, axis::option::growth_t>;
+ using base_t = histogram<std::tuple<axis_t>>;
+
+ // Now we make an accumulator out of it by using inheritance.
+ // We only need to implement operator(). A matching version of operator() is actually
+ // present in base_t, but it is templated and this is not allowed by the accumulator
+ // concept. Initialization could also happen here. We don't need to initialize anything
+ // here, because the default constructor of base_t is called automatically and
+ // sufficient for this example.
+ struct hist_t : base_t {
+ void operator()(const double x) { base_t::operator()(x); }
+ };
+
+ auto h = make_histogram_with(dense_storage<hist_t>(), axis::integer<>(1, 4));
+
+ auto x = {1, 1, 2, 2};
+ auto s = {1, 2, 3, 3}; // samples are filled into the nested histograms
+ h.fill(x, sample(s));
+
+ std::ostringstream os;
+ for (auto&& x : indexed(h)) {
+ os << x.bin() << " ";
+ for (auto&& y : indexed(*x)) { os << "(" << y.bin() << ": " << *y << ") "; }
+ os << "\n";
+ }
+
+ std::cout << os.str() << std::flush;
+ assert(os.str() == "1 (1: 1) (2: 1) \n"
+ "2 (3: 2) \n"
+ "3 \n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_custom_accumulators_simple.cpp b/src/boost/libs/histogram/examples/guide_custom_accumulators_simple.cpp
new file mode 100644
index 000000000..3e8bec478
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_custom_accumulators_simple.cpp
@@ -0,0 +1,44 @@
+// Copyright 2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_custom_accumulators_simple
+
+#include <boost/format.hpp>
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+
+int main() {
+ using namespace boost::histogram;
+
+ // A custom accumulator which tracks the maximum of the samples.
+ // It must have a call operator that accepts the argument of the `sample` function.
+ struct maximum {
+ // return value is ignored, so we use void
+ void operator()(double x) {
+ if (x > value) value = x;
+ }
+ double value = 0; // value is public and initialized to zero
+ };
+
+ // Create 1D histogram that uses the custom accumulator.
+ auto h = make_histogram_with(dense_storage<maximum>(), axis::integer<>(0, 2));
+ h(0, sample(1.0)); // sample goes to first cell
+ h(0, sample(2.0)); // sample goes to first cell
+ h(1, sample(3.0)); // sample goes to second cell
+ h(1, sample(4.0)); // sample goes to second cell
+
+ std::ostringstream os;
+ for (auto&& x : indexed(h)) {
+ os << boost::format("index %i maximum %.1f\n") % x.index() % x->value;
+ }
+ std::cout << os.str() << std::flush;
+ assert(os.str() == "index 0 maximum 2.0\n"
+ "index 1 maximum 4.0\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_custom_accumulators_with_metadata.cpp b/src/boost/libs/histogram/examples/guide_custom_accumulators_with_metadata.cpp
new file mode 100644
index 000000000..478f97842
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_custom_accumulators_with_metadata.cpp
@@ -0,0 +1,47 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_custom_accumulators_with_metadata
+
+#include <boost/histogram.hpp>
+#include <cmath>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+int main() {
+ using namespace boost::histogram;
+
+ // derive custom accumulator from one of the builtins
+ struct accumulator_with_metadata : accumulators::count<> {
+ std::string meta; // custom meta data
+
+ // arbitrary additional data and interface could be added here
+ };
+
+ // make 1D histogram with custom accmulator
+ auto h = make_histogram_with(dense_storage<accumulator_with_metadata>(),
+ axis::integer<>(1, 4));
+
+ // fill some weighted entries
+ auto x = {1, 0, 2, 1};
+ h.fill(x);
+
+ // assigning meta data to two bins
+ h[0].meta = "Foo";
+ h[2].meta = "Bar";
+
+ std::ostringstream os;
+ for (auto&& x : indexed(h))
+ os << x.bin() << " value " << x->value() << " meta " << x->meta << "\n";
+
+ std::cout << os.str() << std::flush;
+ assert(os.str() == "1 value 2 meta Foo\n"
+ "2 value 1 meta \n"
+ "3 value 0 meta Bar\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_custom_minimal_axis.cpp b/src/boost/libs/histogram/examples/guide_custom_minimal_axis.cpp
new file mode 100644
index 000000000..21c5fd5ce
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_custom_minimal_axis.cpp
@@ -0,0 +1,41 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_custom_minimal_axis
+
+#include <boost/histogram.hpp>
+#include <cassert>
+
+int main() {
+ using namespace boost::histogram;
+
+ // stateless axis which returns 1 if the input is even and 0 otherwise
+ struct even_odd_axis {
+ axis::index_type index(int x) const { return x % 2; }
+ axis::index_type size() const { return 2; }
+ };
+
+ // threshold axis which returns 1 if the input is above threshold
+ struct threshold_axis {
+ threshold_axis(double x) : thr(x) {}
+ axis::index_type index(double x) const { return x >= thr; }
+ axis::index_type size() const { return 2; }
+ double thr;
+ };
+
+ auto h = make_histogram(even_odd_axis(), threshold_axis(3.0));
+
+ h(0, 2.0);
+ h(1, 4.0);
+ h(2, 4.0);
+
+ assert(h.at(0, 0) == 1); // even, below threshold
+ assert(h.at(0, 1) == 1); // even, above threshold
+ assert(h.at(1, 0) == 0); // odd, below threshold
+ assert(h.at(1, 1) == 1); // odd, above threshold
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_custom_modified_axis.cpp b/src/boost/libs/histogram/examples/guide_custom_modified_axis.cpp
new file mode 100644
index 000000000..87e2aa094
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_custom_modified_axis.cpp
@@ -0,0 +1,47 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_custom_modified_axis
+
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+
+int main() {
+ using namespace boost::histogram;
+
+ // custom axis, which adapts builtin integer axis
+ struct custom_axis : public axis::integer<> {
+ using value_type = const char*; // type that is fed to the axis
+
+ using integer::integer; // inherit ctors of base
+
+ // the customization point
+ // - accept const char* and convert to int
+ // - then call index method of base class
+ axis::index_type index(value_type s) const { return integer::index(std::atoi(s)); }
+ };
+
+ auto h = make_histogram(custom_axis(3, 6));
+ h("-10");
+ h("3");
+ h("4");
+ h("9");
+
+ std::ostringstream os;
+ for (auto&& b : indexed(h)) {
+ os << "bin " << b.index() << " [" << b.bin() << "] " << *b << "\n";
+ }
+
+ std::cout << os.str() << std::endl;
+
+ assert(os.str() == "bin 0 [3] 1\n"
+ "bin 1 [4] 1\n"
+ "bin 2 [5] 0\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_custom_storage.cpp b/src/boost/libs/histogram/examples/guide_custom_storage.cpp
new file mode 100644
index 000000000..6737df7e0
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_custom_storage.cpp
@@ -0,0 +1,47 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_custom_storage
+
+#include <algorithm> // std::for_each
+#include <array>
+#include <boost/histogram.hpp>
+#include <boost/histogram/algorithm/sum.hpp>
+#include <functional> // std::ref
+#include <unordered_map>
+#include <vector>
+
+int main() {
+ using namespace boost::histogram;
+ const auto axis = axis::regular<>(10, 0.0, 1.0);
+
+ auto data = {0.1, 0.3, 0.2, 0.7};
+
+ // Create static histogram with vector<int> as counter storage, you can use
+ // other arithmetic types as counters, e.g. double.
+ auto h1 = make_histogram_with(std::vector<int>(), axis);
+ std::for_each(data.begin(), data.end(), std::ref(h1));
+ assert(algorithm::sum(h1) == 4);
+
+ // Create static histogram with array<int, N> as counter storage which is
+ // allocated completely on the stack (this is very fast). N may be larger than
+ // the actual number of bins used; an exception is raised if N is too small to
+ // hold all bins.
+ auto h2 = make_histogram_with(std::array<int, 12>(), axis);
+ std::for_each(data.begin(), data.end(), std::ref(h2));
+ assert(algorithm::sum(h2) == 4);
+
+ // Create static histogram with unordered_map as counter storage; this
+ // generates a sparse histogram where only memory is allocated for bins that
+ // are non-zero. This sounds like a good idea for high-dimensional histograms,
+ // but maps come with a memory and run-time overhead. The default_storage
+ // usually performs better in high dimensions.
+ auto h3 = make_histogram_with(std::unordered_map<std::size_t, int>(), axis);
+ std::for_each(data.begin(), data.end(), std::ref(h3));
+ assert(algorithm::sum(h3) == 4);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_fill_histogram.cpp b/src/boost/libs/histogram/examples/guide_fill_histogram.cpp
new file mode 100644
index 000000000..172be66e0
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_fill_histogram.cpp
@@ -0,0 +1,61 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_fill_histogram
+
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <functional>
+#include <numeric>
+#include <utility>
+#include <vector>
+
+int main() {
+ using namespace boost::histogram;
+
+ auto h = make_histogram(axis::integer<>(0, 3), axis::regular<>(2, 0.0, 1.0));
+
+ // fill histogram, number of arguments must be equal to number of axes,
+ // types must be convertible to axis value type (here integer and double)
+ h(0, 0.2); // increase a cell value by one
+ h(2, 0.5); // increase another cell value by one
+
+ // fills from a tuple are also supported; passing a tuple of wrong size
+ // causes an error at compile-time or an assertion at runtime in debug mode
+ auto xy = std::make_tuple(1, 0.3);
+ h(xy);
+
+ // chunk-wise filling is also supported and more efficient, make some data...
+ std::vector<double> xy2[2] = {{0, 2, 5}, {0.8, 0.4, 0.7}};
+
+ // ... and call fill method
+ h.fill(xy2);
+
+ // once histogram is filled, access individual cells using operator[] or at(...)
+ // - operator[] can only accept a single argument in the current version of C++,
+ // it is convenient when you have a 1D histogram
+ // - at(...) can accept several values, so use this by default
+ // - underflow bins are at index -1, overflow bins at index `size()`
+ // - passing an invalid index triggers a std::out_of_range exception
+ assert(h.at(0, 0) == 1);
+ assert(h.at(0, 1) == 1);
+ assert(h.at(1, 0) == 1);
+ assert(h.at(1, 1) == 0);
+ assert(h.at(2, 0) == 1);
+ assert(h.at(2, 1) == 1);
+ assert(h.at(-1, -1) == 0); // underflow for axis 0 and 1
+ assert(h.at(-1, 0) == 0); // underflow for axis 0, normal bin for axis 1
+ assert(h.at(-1, 2) == 0); // underflow for axis 0, overflow for axis 1
+ assert(h.at(3, 1) == 1); // overflow for axis 0, normal bin for axis 1
+
+ // iteration over values works, but see next example for a better way
+ // - iteration using begin() and end() includes under- and overflow bins
+ // - iteration order is an implementation detail and should not be relied upon
+ const double sum = std::accumulate(h.begin(), h.end(), 0.0);
+ assert(sum == 6);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_fill_profile.cpp b/src/boost/libs/histogram/examples/guide_fill_profile.cpp
new file mode 100644
index 000000000..55d650815
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_fill_profile.cpp
@@ -0,0 +1,53 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_fill_profile
+
+#include <boost/format.hpp>
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+#include <tuple>
+
+int main() {
+ using namespace boost::histogram;
+
+ // make a profile, it computes the mean of the samples in each histogram cell
+ auto h = make_profile(axis::integer<>(0, 3));
+
+ // mean is computed from the values marked with the sample() helper function
+ h(0, sample(1)); // sample goes to cell 0
+ h(0, sample(2)); // sample goes to cell 0
+ h(1, sample(3)); // sample goes to cell 1
+ h(sample(4), 1); // sample goes to cell 1; sample can be first or last argument
+
+ // fills from tuples are also supported, 5 and 6 go to cell 2
+ auto a = std::make_tuple(2, sample(5));
+ auto b = std::make_tuple(sample(6), 2);
+ h(a);
+ h(b);
+
+ // builtin accumulators have methods to access their state
+ std::ostringstream os;
+ for (auto&& x : indexed(h)) {
+ // use `.` to access methods of accessor, like `index()`
+ // use `->` to access methods of accumulator
+ const auto i = x.index();
+ const auto n = x->count(); // how many samples are in this bin
+ const auto vl = x->value(); // mean value
+ const auto vr = x->variance(); // estimated variance of the mean value
+ os << boost::format("index %i count %i value %.1f variance %.1f\n") % i % n % vl % vr;
+ }
+
+ std::cout << os.str() << std::flush;
+
+ assert(os.str() == "index 0 count 2 value 1.5 variance 0.5\n"
+ "index 1 count 2 value 3.5 variance 0.5\n"
+ "index 2 count 2 value 5.5 variance 0.5\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_fill_weighted_histogram.cpp b/src/boost/libs/histogram/examples/guide_fill_weighted_histogram.cpp
new file mode 100644
index 000000000..487e1c33a
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_fill_weighted_histogram.cpp
@@ -0,0 +1,36 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_fill_weighted_histogram
+
+#include <boost/histogram.hpp>
+#include <cassert>
+
+int main() {
+ using namespace boost::histogram;
+
+ // Create a histogram with weight counters that keep track of a variance estimate.
+ auto h = make_weighted_histogram(axis::regular<>(3, 0.0, 1.0));
+
+ h(0.0, weight(1)); // weight 1 goes to first bin
+ h(0.1, weight(2)); // weight 2 goes to first bin
+ h(0.4, weight(3)); // weight 3 goes to second bin
+ h(0.5, weight(4)); // weight 4 goes to second bin
+
+ // chunk-wise filling is also supported
+ auto x = {0.2, 0.6};
+ auto w = {5, 6};
+ h.fill(x, weight(w));
+
+ // Weight counters have methods to access the value (sum of weights) and the variance
+ // (sum of weights squared, why this gives the variance is explained in the rationale)
+ assert(h[0].value() == 1 + 2 + 5);
+ assert(h[0].variance() == 1 * 1 + 2 * 2 + 5 * 5);
+ assert(h[1].value() == 3 + 4 + 6);
+ assert(h[1].variance() == 3 * 3 + 4 * 4 + 6 * 6);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_fill_weighted_profile.cpp b/src/boost/libs/histogram/examples/guide_fill_weighted_profile.cpp
new file mode 100644
index 000000000..767bfad86
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_fill_weighted_profile.cpp
@@ -0,0 +1,51 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_fill_weighted_profile
+
+#include <boost/format.hpp>
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+
+int main() {
+ using namespace boost::histogram;
+ using namespace boost::histogram::literals; // _c suffix creates compile-time numbers
+
+ // make 2D weighted profile
+ auto h = make_weighted_profile(axis::integer<>(0, 2), axis::integer<>(0, 2));
+
+ // The mean is computed from the values marked with the sample() helper function.
+ // Weights can be passed as well. The `sample` and `weight` arguments can appear in any
+ // order, but they must be the first or last arguments.
+ h(0, 0, sample(1)); // sample goes to cell (0, 0); weight is 1
+ h(0, 0, sample(2), weight(3)); // sample goes to cell (0, 0); weight is 3
+ h(1, 0, sample(3)); // sample goes to cell (1, 0); weight is 1
+ h(1, 0, sample(4)); // sample goes to cell (1, 0); weight is 1
+ h(0, 1, sample(5)); // sample goes to cell (1, 0); weight is 1
+ h(0, 1, sample(6)); // sample goes to cell (1, 0); weight is 1
+ h(1, 1, weight(4), sample(7)); // sample goes to cell (1, 1); weight is 4
+ h(weight(5), sample(8), 1, 1); // sample goes to cell (1, 1); weight is 5
+
+ std::ostringstream os;
+ for (auto&& x : indexed(h)) {
+ const auto i = x.index(0_c);
+ const auto j = x.index(1_c);
+ const auto m = x->value(); // weighted mean
+ const auto v = x->variance(); // estimated variance of weighted mean
+ os << boost::format("index %i,%i mean %.1f variance %.1f\n") % i % j % m % v;
+ }
+
+ std::cout << os.str() << std::flush;
+
+ assert(os.str() == "index 0,0 mean 1.8 variance 0.5\n"
+ "index 1,0 mean 3.5 variance 0.5\n"
+ "index 0,1 mean 5.5 variance 0.5\n"
+ "index 1,1 mean 7.6 variance 0.5\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_histogram_in_api.cpp b/src/boost/libs/histogram/examples/guide_histogram_in_api.cpp
new file mode 100644
index 000000000..1011e6885
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_histogram_in_api.cpp
@@ -0,0 +1,57 @@
+// Copyright 2020 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_histogram_in_api
+
+#include <boost/histogram.hpp>
+#include <cassert>
+
+// function accepts any histogram and returns a copy
+template <class Axes, class Storage>
+boost::histogram::histogram<Axes, Storage> any_histogram(
+ boost::histogram::histogram<Axes, Storage>& h) {
+ return h;
+}
+
+// function only accepts histograms with fixed axis types and returns a copy
+template <class Storage, class... Axes>
+boost::histogram::histogram<std::tuple<Axes...>, Storage> only_static_histogram(
+ boost::histogram::histogram<std::tuple<Axes...>, Storage>& h) {
+ return h;
+}
+
+// function only accepts histograms with dynamic axis types and returns a copy
+template <class Storage, class... Axes>
+boost::histogram::histogram<std::vector<boost::histogram::axis::variant<Axes...>>,
+ Storage>
+only_dynamic_histogram(
+ boost::histogram::histogram<std::vector<boost::histogram::axis::variant<Axes...>>,
+ Storage>& h) {
+ return h;
+}
+
+int main() {
+ using namespace boost::histogram;
+
+ auto histogram_with_static_axes = make_histogram(axis::regular<>(10, 0, 1));
+
+ using axis_variant = axis::variant<axis::regular<>, axis::integer<>>;
+ std::vector<axis_variant> axes;
+ axes.emplace_back(axis::regular<>(5, 0, 1));
+ axes.emplace_back(axis::integer<>(0, 1));
+ auto histogram_with_dynamic_axes = make_histogram(axes);
+
+ assert(any_histogram(histogram_with_static_axes) == histogram_with_static_axes);
+ assert(any_histogram(histogram_with_dynamic_axes) == histogram_with_dynamic_axes);
+ assert(only_static_histogram(histogram_with_static_axes) == histogram_with_static_axes);
+ assert(only_dynamic_histogram(histogram_with_dynamic_axes) ==
+ histogram_with_dynamic_axes);
+
+ // does not compile: only_static_histogram(histogram_with_dynamic_axes)
+ // does not compile: only_dynamic_histogram(histogram_with_static_axes)
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_histogram_operators.cpp b/src/boost/libs/histogram/examples/guide_histogram_operators.cpp
new file mode 100644
index 000000000..e4059edc5
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_histogram_operators.cpp
@@ -0,0 +1,62 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_histogram_operators
+
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <vector>
+
+int main() {
+ using namespace boost::histogram;
+
+ // make two histograms
+ auto h1 = make_histogram(axis::regular<>(2, -1.0, 1.0));
+ auto h2 = make_histogram(axis::regular<>(2, -1.0, 1.0));
+
+ h1(-0.5); // counts are: 1 0
+ h2(0.5); // counts are: 0 1
+
+ // add them
+ auto h3 = h1;
+ h3 += h2; // counts are: 1 1
+
+ // adding multiple histograms at once is likely to be optimized by the compiler so that
+ // superfluous temporaries avoided, but no guarantees are given; use this equivalent
+ // code when you want to make sure: h4 = h1; h4 += h2; h4 += h3;
+ auto h4 = h1 + h2 + h3; // counts are: 2 2
+
+ assert(h4.at(0) == 2 && h4.at(1) == 2);
+
+ // multiply by number, h4 *= 2 also works
+ auto h5 = h4 * 2; // counts are: 4 4
+
+ // divide by number; s4 /= 4 also works
+ auto h6 = h5 / 4; // counts are: 1 1
+
+ assert(h6.at(0) == 1 && h6.at(1) == 1);
+ assert(h6 != h5 && h5 == 4 * h6);
+
+ // note the special effect of multiplication on weight_storage
+ auto h = make_histogram_with(weight_storage(), axis::regular<>(2, -1.0, 1.0));
+ h(-0.5);
+
+ // counts are: 1 0
+ assert(h.at(0).value() == 1 && h.at(1).value() == 0);
+
+ auto h_sum = h + h;
+ auto h_mul = 2 * h;
+
+ // values are the same as expected...
+ assert(h_sum.at(0).value() == h_mul.at(0).value());
+ // ... but variances differ
+ assert(h_sum.at(0).variance() == 2 && h_mul.at(0).variance() == 4);
+
+ // equality operator checks variances, so histograms are not equal
+ assert(h_sum != h_mul);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_histogram_projection.cpp b/src/boost/libs/histogram/examples/guide_histogram_projection.cpp
new file mode 100644
index 000000000..54f452125
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_histogram_projection.cpp
@@ -0,0 +1,58 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_histogram_projection
+
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+
+int main() {
+ using namespace boost::histogram;
+ using namespace literals; // enables _c suffix
+
+ // make a 2d histogram
+ auto h = make_histogram(axis::regular<>(3, -1.0, 1.0), axis::integer<>(0, 2));
+
+ h(-0.9, 0);
+ h(0.9, 1);
+ h(0.1, 0);
+
+ auto hr0 = algorithm::project(h, 0_c); // keep only first axis
+ auto hr1 = algorithm::project(h, 1_c); // keep only second axis
+
+ // reduce does not remove counts; returned histograms are summed over
+ // the removed axes, so h, hr0, and hr1 have same number of total counts;
+ // we compute the sum of counts with the sum algorithm
+ assert(algorithm::sum(h) == 3 && algorithm::sum(hr0) == 3 && algorithm::sum(hr1) == 3);
+
+ std::ostringstream os1;
+ for (auto&& x : indexed(h))
+ os1 << "(" << x.index(0) << ", " << x.index(1) << "): " << *x << "\n";
+ std::cout << os1.str() << std::flush;
+ assert(os1.str() == "(0, 0): 1\n"
+ "(1, 0): 1\n"
+ "(2, 0): 0\n"
+ "(0, 1): 0\n"
+ "(1, 1): 0\n"
+ "(2, 1): 1\n");
+
+ std::ostringstream os2;
+ for (auto&& x : indexed(hr0)) os2 << "(" << x.index(0) << ", -): " << *x << "\n";
+ std::cout << os2.str() << std::flush;
+ assert(os2.str() == "(0, -): 1\n"
+ "(1, -): 1\n"
+ "(2, -): 1\n");
+
+ std::ostringstream os3;
+ for (auto&& x : indexed(hr1)) os3 << "(- ," << x.index(0) << "): " << *x << "\n";
+ std::cout << os3.str() << std::flush;
+ assert(os3.str() == "(- ,0): 2\n"
+ "(- ,1): 1\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_histogram_reduction.cpp b/src/boost/libs/histogram/examples/guide_histogram_reduction.cpp
new file mode 100644
index 000000000..677625305
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_histogram_reduction.cpp
@@ -0,0 +1,48 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_histogram_reduction
+
+#include <boost/histogram.hpp>
+#include <cassert>
+
+int main() {
+ using namespace boost::histogram;
+ // import reduce commands into local namespace to save typing
+ using algorithm::rebin;
+ using algorithm::shrink;
+ using algorithm::slice;
+
+ // make a 2d histogram
+ auto h = make_histogram(axis::regular<>(4, 0.0, 4.0), axis::regular<>(4, -2.0, 2.0));
+
+ h(0, -0.9);
+ h(1, 0.9);
+ h(2, 0.1);
+ h(3, 0.1);
+
+ // reduce takes positional commands which are applied to the axes in order
+ // - shrink is applied to the first axis; the new axis range is 0.0 to 3.0
+ // - rebin is applied to the second axis; pairs of adjacent bins are merged
+ auto h2 = algorithm::reduce(h, shrink(0.0, 3.0), rebin(2));
+
+ assert(h2.axis(0) == axis::regular<>(3, 0.0, 3.0));
+ assert(h2.axis(1) == axis::regular<>(2, -2.0, 2.0));
+
+ // reduce does not change the total count if the histogram has underflow/overflow bins
+ assert(algorithm::sum(h) == 4 && algorithm::sum(h2) == 4);
+
+ // One can also explicitly specify the index of the axis in the histogram on which the
+ // command should act, by using this index as the the first parameter. The position of
+ // the command in the argument list of reduce is then ignored. We use this to slice only
+ // the second axis (axis has index 1 in the histogram) from bin index 2 to 4.
+ auto h3 = algorithm::reduce(h, slice(1, 2, 4));
+
+ assert(h3.axis(0) == h.axis(0)); // unchanged
+ assert(h3.axis(1) == axis::regular<>(2, 0.0, 2.0));
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_histogram_serialization.cpp b/src/boost/libs/histogram/examples/guide_histogram_serialization.cpp
new file mode 100644
index 000000000..c00ef3cd6
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_histogram_serialization.cpp
@@ -0,0 +1,47 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_histogram_serialization
+
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/histogram.hpp>
+#include <boost/histogram/serialization.hpp> // includes serialization code
+#include <cassert>
+#include <sstream>
+
+int main() {
+ using namespace boost::histogram;
+
+ auto a = make_histogram(axis::regular<>(3, -1.0, 1.0, "axis 0"),
+ axis::integer<>(0, 2, "axis 1"));
+ a(0.5, 1);
+
+ std::string buf; // to hold persistent representation
+
+ // store histogram
+ {
+ std::ostringstream os;
+ boost::archive::text_oarchive oa(os);
+ oa << a;
+ buf = os.str();
+ }
+
+ auto b = decltype(a)(); // create a default-constructed second histogram
+
+ assert(b != a); // b is empty, a is not
+
+ // load histogram
+ {
+ std::istringstream is(buf);
+ boost::archive::text_iarchive ia(is);
+ ia >> b;
+ }
+
+ assert(b == a); // now b is equal to a
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_histogram_streaming.cpp b/src/boost/libs/histogram/examples/guide_histogram_streaming.cpp
new file mode 100644
index 000000000..71407e71f
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_histogram_streaming.cpp
@@ -0,0 +1,62 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_histogram_streaming
+
+#include <boost/histogram.hpp>
+#include <boost/histogram/ostream.hpp>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+int main() {
+ using namespace boost::histogram;
+
+ std::ostringstream os;
+
+ // width of histogram can be set like this; if it is not set, the library attempts to
+ // determine the terminal width and choses the histogram width accordingly
+ os.width(78);
+
+ auto h1 = make_histogram(axis::regular<>(5, -1.0, 1.0, "axis 1"));
+ h1.at(0) = 2;
+ h1.at(1) = 4;
+ h1.at(2) = 3;
+ h1.at(4) = 1;
+
+ // 1D histograms are rendered as an ASCII drawing
+ os << h1;
+
+ auto h2 = make_histogram(axis::regular<>(2, -1.0, 1.0, "axis 1"),
+ axis::category<std::string>({"red", "blue"}, "axis 2"));
+
+ // higher dimensional histograms just have their cell counts listed
+ os << h2;
+
+ std::cout << os.str() << std::endl;
+
+ assert(
+ os.str() ==
+ "histogram(regular(5, -1, 1, metadata=\"axis 1\", options=underflow | overflow))\n"
+ " ┌─────────────────────────────────────────────────────────────┐\n"
+ "[-inf, -1) 0 │ │\n"
+ "[ -1, -0.6) 2 │██████████████████████████████ │\n"
+ "[-0.6, -0.2) 4 │████████████████████████████████████████████████████████████ │\n"
+ "[-0.2, 0.2) 3 │█████████████████████████████████████████████ │\n"
+ "[ 0.2, 0.6) 0 │ │\n"
+ "[ 0.6, 1) 1 │███████████████ │\n"
+ "[ 1, inf) 0 │ │\n"
+ " └─────────────────────────────────────────────────────────────┘\n"
+ "histogram(\n"
+ " regular(2, -1, 1, metadata=\"axis 1\", options=underflow | overflow)\n"
+ " category(\"red\", \"blue\", metadata=\"axis 2\", options=overflow)\n"
+ " (-1 0): 0 ( 0 0): 0 ( 1 0): 0 ( 2 0): 0 (-1 1): 0 ( 0 1): 0\n"
+ " ( 1 1): 0 ( 2 1): 0 (-1 2): 0 ( 0 2): 0 ( 1 2): 0 ( 2 2): 0\n"
+ ")");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_indexed_access.cpp b/src/boost/libs/histogram/examples/guide_indexed_access.cpp
new file mode 100644
index 000000000..5850c1d3c
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_indexed_access.cpp
@@ -0,0 +1,78 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_indexed_access
+
+#include <boost/format.hpp>
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <iostream>
+#include <numeric> // for std::accumulate
+#include <sstream>
+
+using namespace boost::histogram;
+
+int main() {
+ // make histogram with 2 x 2 = 4 bins (not counting under-/overflow bins)
+ auto h = make_histogram(axis::regular<>(2, -1.0, 1.0), axis::regular<>(2, 2.0, 4.0));
+
+ h(weight(1), -0.5, 2.5); // bin index 0, 0
+ h(weight(2), -0.5, 3.5); // bin index 0, 1
+ h(weight(3), 0.5, 2.5); // bin index 1, 0
+ h(weight(4), 0.5, 3.5); // bin index 1, 1
+
+ // use the `indexed` range adaptor to iterate over all bins;
+ // it is not only more convenient but also faster than a hand-crafted loop!
+ std::ostringstream os;
+ for (auto&& x : indexed(h)) {
+ // x is a special accessor object
+ const auto i = x.index(0); // current index along first axis
+ const auto j = x.index(1); // current index along second axis
+ const auto b0 = x.bin(0); // current bin interval along first axis
+ const auto b1 = x.bin(1); // current bin interval along second axis
+ const auto v = *x; // "dereference" to get the bin value
+ os << boost::format("%i %i [%2i, %i) [%2i, %i): %i\n") % i % j % b0.lower() %
+ b0.upper() % b1.lower() % b1.upper() % v;
+ }
+
+ std::cout << os.str() << std::flush;
+
+ assert(os.str() == "0 0 [-1, 0) [ 2, 3): 1\n"
+ "1 0 [ 0, 1) [ 2, 3): 3\n"
+ "0 1 [-1, 0) [ 3, 4): 2\n"
+ "1 1 [ 0, 1) [ 3, 4): 4\n");
+
+ // `indexed` skips underflow and overflow bins by default, but can be called
+ // with the second argument `coverage::all` to walk over all bins
+ std::ostringstream os2;
+ for (auto&& x : indexed(h, coverage::all)) {
+ os2 << boost::format("%2i %2i: %i\n") % x.index(0) % x.index(1) % *x;
+ }
+
+ std::cout << os2.str() << std::flush;
+
+ assert(os2.str() == "-1 -1: 0\n"
+ " 0 -1: 0\n"
+ " 1 -1: 0\n"
+ " 2 -1: 0\n"
+
+ "-1 0: 0\n"
+ " 0 0: 1\n"
+ " 1 0: 3\n"
+ " 2 0: 0\n"
+
+ "-1 1: 0\n"
+ " 0 1: 2\n"
+ " 1 1: 4\n"
+ " 2 1: 0\n"
+
+ "-1 2: 0\n"
+ " 0 2: 0\n"
+ " 1 2: 0\n"
+ " 2 2: 0\n");
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_make_dynamic_histogram.cpp b/src/boost/libs/histogram/examples/guide_make_dynamic_histogram.cpp
new file mode 100644
index 000000000..80ab025ee
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_make_dynamic_histogram.cpp
@@ -0,0 +1,47 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_make_dynamic_histogram
+
+#include <boost/histogram.hpp>
+#include <cassert>
+#include <sstream>
+#include <vector>
+
+const char* config = "4 1.0 2.0\n"
+ "5 3.0 4.0\n";
+
+int main() {
+ using namespace boost::histogram;
+
+ // read axis config from a config file (mocked here with std::istringstream)
+ // and create vector of regular axes, the number of axis is not known at compile-time
+ std::istringstream is(config);
+ auto v1 = std::vector<axis::regular<>>();
+ while (is.good()) {
+ unsigned bins;
+ double start, stop;
+ is >> bins >> start >> stop;
+ v1.emplace_back(bins, start, stop);
+ }
+
+ // create histogram from iterator range
+ // (copying or moving the vector also works, move is shown below)
+ auto h1 = make_histogram(v1.begin(), v1.end());
+ assert(h1.rank() == v1.size());
+
+ // with a vector of axis::variant (polymorphic axis type that can hold any one of the
+ // template arguments at a time) the types and number of axis can vary at run-time
+ auto v2 = std::vector<axis::variant<axis::regular<>, axis::integer<>>>();
+ v2.emplace_back(axis::regular<>(100, -1.0, 1.0));
+ v2.emplace_back(axis::integer<>(1, 7));
+
+ // create dynamic histogram by moving the vector
+ auto h2 = make_histogram(std::move(v2));
+ assert(h2.rank() == 2);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_make_static_histogram.cpp b/src/boost/libs/histogram/examples/guide_make_static_histogram.cpp
new file mode 100644
index 000000000..55eb4b689
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_make_static_histogram.cpp
@@ -0,0 +1,23 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_make_static_histogram
+
+#include <boost/histogram.hpp>
+#include <cassert>
+
+int main() {
+ using namespace boost::histogram;
+
+ // create a 1d-histogram in default configuration which
+ // covers the real line from -1 to 1 in 100 bins
+ auto h = make_histogram(axis::regular<>(100, -1.0, 1.0));
+
+ // rank is the number of axes
+ assert(h.rank() == 1);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_parallel_filling.cpp b/src/boost/libs/histogram/examples/guide_parallel_filling.cpp
new file mode 100644
index 000000000..7d37fbbbe
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_parallel_filling.cpp
@@ -0,0 +1,50 @@
+// Copyright 2018-2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_parallel_filling
+
+#include <boost/histogram.hpp>
+#include <boost/histogram/algorithm/sum.hpp>
+#include <cassert>
+#include <functional>
+#include <thread>
+#include <vector>
+
+// dummy fill function, to be executed in parallel by several threads
+template <typename Histogram>
+void fill(Histogram& h) {
+ for (unsigned i = 0; i < 1000; ++i) { h(i % 10); }
+}
+
+int main() {
+ using namespace boost::histogram;
+
+ /*
+ Create histogram with container of thread-safe counters for parallel filling in
+ several threads. Only filling is thread-safe, other guarantees are not given.
+ */
+ auto h = make_histogram_with(dense_storage<accumulators::count<unsigned, true>>(),
+ axis::integer<>(0, 10));
+
+ /*
+ Run the fill function in parallel from different threads. This is safe when a
+ thread-safe accumulator and a storage with thread-safe cell access are used.
+ */
+ auto fill_h = [&h]() { fill(h); };
+ std::thread t1(fill_h);
+ std::thread t2(fill_h);
+ std::thread t3(fill_h);
+ std::thread t4(fill_h);
+ t1.join();
+ t2.join();
+ t3.join();
+ t4.join();
+
+ // Without a thread-safe accumulator, this number may be smaller.
+ assert(algorithm::sum(h) == 4000);
+}
+
+//]
diff --git a/src/boost/libs/histogram/examples/guide_stdlib_algorithms.cpp b/src/boost/libs/histogram/examples/guide_stdlib_algorithms.cpp
new file mode 100644
index 000000000..52581787d
--- /dev/null
+++ b/src/boost/libs/histogram/examples/guide_stdlib_algorithms.cpp
@@ -0,0 +1,67 @@
+// Copyright 2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//[ guide_stdlib_algorithms
+
+#include <boost/histogram.hpp>
+#include <cassert>
+
+#include <algorithm> // fill, any_of, min_element, max_element
+#include <cmath> // sqrt
+#include <numeric> // partial_sum, inner_product
+
+int main() {
+ using namespace boost::histogram;
+
+ // make histogram that represents a probability density function (PDF)
+ auto h1 = make_histogram(axis::regular<>(4, 1.0, 3.0));
+
+ // make indexed range to skip underflow and overflow cells
+ auto ind = indexed(h1);
+
+ // use std::fill to set all counters to 0.25 (except under- and overflow counters)
+ std::fill(ind.begin(), ind.end(), 0.25);
+
+ // compute the cumulative density function (CDF), overriding cell values
+ std::partial_sum(ind.begin(), ind.end(), ind.begin());
+
+ assert(h1.at(-1) == 0.00);
+ assert(h1.at(0) == 0.25);
+ assert(h1.at(1) == 0.50);
+ assert(h1.at(2) == 0.75);
+ assert(h1.at(3) == 1.00);
+ assert(h1.at(4) == 0.00);
+
+ // use any_of to check if any cell values are smaller than 0.1,
+ auto b = std::any_of(ind.begin(), ind.end(), [](const auto& x) { return x < 0.1; });
+ assert(b == false); // under- and overflow cells are zero, but skipped
+
+ // find minimum element
+ auto min_it = std::min_element(ind.begin(), ind.end());
+ assert(*min_it == 0.25); // under- and overflow cells are skipped
+
+ // find maximum element
+ auto max_it = std::max_element(ind.begin(), ind.end());
+ assert(*max_it == 1.0);
+
+ // make second PDF
+ auto h2 = make_histogram(axis::regular<>(4, 1.0, 4.0));
+ h2.at(0) = 0.1;
+ h2.at(1) = 0.3;
+ h2.at(2) = 0.2;
+ h2.at(3) = 0.4;
+
+ // computing cosine similiarity: cos(theta) = A dot B / sqrt((A dot A) * (B dot B))
+ auto ind2 = indexed(h2);
+ const auto aa = std::inner_product(ind.begin(), ind.end(), ind.begin(), 0.0);
+ const auto bb = std::inner_product(ind2.begin(), ind2.end(), ind2.begin(), 0.0);
+ const auto ab = std::inner_product(ind.begin(), ind.end(), ind2.begin(), 0.0);
+ const auto cos_sim = ab / std::sqrt(aa * bb);
+
+ assert(std::abs(cos_sim - 0.967) < 1e-2);
+}
+
+//]