From 9abbe46e3dd57e2b55f7ab52eaed15994f76ae52 Mon Sep 17 00:00:00 2001 From: Hans Dembinski Date: Sun, 17 Feb 2019 13:37:50 +0100 Subject: [PATCH] CI & doc update, removed multiprecision::cpp_int, simpler axis implementation, use_default to set default options * Travis uses b2 and codecov now * replacing boost::multiprecision with custom implementation to avoid the dependency * improved axis implementation: `update` is now a normal method * introduced use_default tag type to set defaults * whitespace fixes and doc update --- .gitignore | 8 +- .travis.yml | 146 +- CMakeLists.txt | 33 +- Jamfile | 33 +- README.md | 4 +- benchmark/speed_root.cpp | 4 +- doc/guide.qbk | 48 +- doc/rationale.qbk | 2 +- doc/src/boostbook.css | 716 - doc/src/images/alert.png | Bin 603 -> 0 bytes doc/src/images/blank.png | Bin 374 -> 0 bytes doc/src/images/boost.png | Bin 6308 -> 0 bytes doc/src/images/callouts/1.png | Bin 391 -> 0 bytes doc/src/images/callouts/1.svg | 15 - doc/src/images/callouts/10.png | Bin 485 -> 0 bytes doc/src/images/callouts/10.svg | 18 - doc/src/images/callouts/11.png | Bin 410 -> 0 bytes doc/src/images/callouts/11.svg | 16 - doc/src/images/callouts/12.png | Bin 488 -> 0 bytes doc/src/images/callouts/12.svg | 18 - doc/src/images/callouts/13.png | Bin 509 -> 0 bytes doc/src/images/callouts/13.svg | 20 - doc/src/images/callouts/14.png | Bin 499 -> 0 bytes doc/src/images/callouts/14.svg | 17 - doc/src/images/callouts/15.png | Bin 507 -> 0 bytes doc/src/images/callouts/15.svg | 19 - doc/src/images/callouts/16.svg | 20 - doc/src/images/callouts/17.svg | 17 - doc/src/images/callouts/18.svg | 21 - doc/src/images/callouts/19.svg | 20 - doc/src/images/callouts/2.png | Bin 446 -> 0 bytes doc/src/images/callouts/2.svg | 17 - doc/src/images/callouts/20.svg | 20 - doc/src/images/callouts/21.svg | 18 - doc/src/images/callouts/22.svg | 20 - doc/src/images/callouts/23.svg | 22 - doc/src/images/callouts/24.svg | 19 - doc/src/images/callouts/25.svg | 21 - doc/src/images/callouts/26.svg | 22 - doc/src/images/callouts/27.svg | 19 - doc/src/images/callouts/28.svg | 23 - doc/src/images/callouts/29.svg | 22 - doc/src/images/callouts/3.png | Bin 431 -> 0 bytes doc/src/images/callouts/3.svg | 19 - doc/src/images/callouts/30.svg | 22 - doc/src/images/callouts/4.png | Bin 441 -> 0 bytes doc/src/images/callouts/4.svg | 16 - doc/src/images/callouts/5.png | Bin 423 -> 0 bytes doc/src/images/callouts/5.svg | 18 - doc/src/images/callouts/6.png | Bin 431 -> 0 bytes doc/src/images/callouts/6.svg | 19 - doc/src/images/callouts/7.png | Bin 397 -> 0 bytes doc/src/images/callouts/7.svg | 16 - doc/src/images/callouts/8.png | Bin 434 -> 0 bytes doc/src/images/callouts/8.svg | 20 - doc/src/images/callouts/9.png | Bin 420 -> 0 bytes doc/src/images/callouts/9.svg | 19 - doc/src/images/caution.png | Bin 1250 -> 0 bytes doc/src/images/caution.svg | 68 - doc/src/images/draft.png | Bin 17454 -> 0 bytes doc/src/images/home.png | Bin 358 -> 0 bytes doc/src/images/home.svg | 26 - doc/src/images/important.png | Bin 722 -> 0 bytes doc/src/images/important.svg | 25 - doc/src/images/next.png | Bin 336 -> 0 bytes doc/src/images/next.svg | 19 - doc/src/images/next_disabled.png | Bin 1110 -> 0 bytes doc/src/images/note.png | Bin 490 -> 0 bytes doc/src/images/note.svg | 33 - doc/src/images/prev.png | Bin 334 -> 0 bytes doc/src/images/prev.svg | 19 - doc/src/images/prev_disabled.png | Bin 1109 -> 0 bytes doc/src/images/smiley.png | Bin 867 -> 0 bytes doc/src/images/tip.png | Bin 449 -> 0 bytes doc/src/images/tip.svg | 84 - doc/src/images/toc-blank.png | Bin 318 -> 0 bytes doc/src/images/toc-minus.png | Bin 259 -> 0 bytes doc/src/images/toc-plus.png | Bin 264 -> 0 bytes doc/src/images/up.png | Bin 370 -> 0 bytes doc/src/images/up.svg | 19 - doc/src/images/up_disabled.png | Bin 1115 -> 0 bytes doc/src/images/warning.png | Bin 1241 -> 0 bytes doc/src/images/warning.svg | 23 - doc/storage_3_cpp_int.svg | 2 +- examples/Jamfile | 23 +- examples/getting_started_listing_01.cpp | 50 +- examples/getting_started_listing_02.cpp | 30 +- examples/getting_started_listing_03.cpp | 29 +- examples/guide_axis_basic_demo.cpp | 25 +- examples/guide_axis_circular.cpp | 31 +- examples/guide_axis_growing.cpp | 65 + examples/guide_axis_with_uoflow_off.cpp | 7 +- examples/guide_custom_accumulators.cpp | 24 +- examples/guide_custom_modified_axis.cpp | 1 + examples/guide_custom_storage.cpp | 21 +- examples/guide_fill_accumulator.cpp | 53 + examples/guide_fill_histogram.cpp | 43 +- examples/guide_fill_profile.cpp | 53 + examples/guide_histogram_reduction.cpp | 1 + examples/guide_histogram_streaming.cpp | 5 +- ...in_counts.cpp => guide_indexed_access.cpp} | 23 +- examples/guide_parallel_filling.cpp | 19 +- include/boost/histogram.hpp | 2 +- include/boost/histogram/algorithm/project.hpp | 3 +- include/boost/histogram/axis/category.hpp | 76 +- include/boost/histogram/axis/integer.hpp | 117 +- include/boost/histogram/axis/option.hpp | 86 +- include/boost/histogram/axis/ostream.hpp | 115 +- include/boost/histogram/axis/regular.hpp | 168 +- include/boost/histogram/axis/traits.hpp | 35 +- include/boost/histogram/axis/variable.hpp | 115 +- include/boost/histogram/axis/variant.hpp | 30 +- include/boost/histogram/detail/linearize.hpp | 95 +- include/boost/histogram/detail/meta.hpp | 14 +- include/boost/histogram/fwd.hpp | 27 +- include/boost/histogram/histogram.hpp | 4 +- include/boost/histogram/indexed.hpp | 7 +- include/boost/histogram/serialization.hpp | 15 +- include/boost/histogram/unlimited_storage.hpp | 348 +- test/Jamfile | 92 +- test/algorithm_project_test.cpp | 2 +- test/algorithm_reduce_test.cpp | 17 +- test/axis_integer_test.cpp | 2 + test/axis_option_test.cpp | 52 +- test/axis_regular_test.cpp | 9 +- test/axis_traits_test.cpp | 76 +- test/axis_variant_test.cpp | 5 +- test/histogram_dynamic_test.cpp | 13 +- test/histogram_growing_test.cpp | 168 +- test/histogram_serialization_test.cpp | 19 +- test/histogram_serialization_test_dynamic.xml | 19220 +++++++++++++++- test/histogram_serialization_test_static.xml | 19220 +++++++++++++++- test/histogram_test.cpp | 12 +- test/linearize_test.cpp | 10 +- test/meta_test.cpp | 6 +- test/storage_adaptor_serialization_test.cpp | 11 +- test/unlimited_storage_test.cpp | 120 +- test/utility_serialization.hpp | 12 +- tools/cov.sh | 36 + tools/pass_on_fail.py | 24 - tools/travis_install_boost.sh | 19 - 141 files changed, 40058 insertions(+), 2732 deletions(-) delete mode 100644 doc/src/boostbook.css delete mode 100644 doc/src/images/alert.png delete mode 100644 doc/src/images/blank.png delete mode 100644 doc/src/images/boost.png delete mode 100644 doc/src/images/callouts/1.png delete mode 100644 doc/src/images/callouts/1.svg delete mode 100644 doc/src/images/callouts/10.png delete mode 100644 doc/src/images/callouts/10.svg delete mode 100644 doc/src/images/callouts/11.png delete mode 100644 doc/src/images/callouts/11.svg delete mode 100644 doc/src/images/callouts/12.png delete mode 100644 doc/src/images/callouts/12.svg delete mode 100644 doc/src/images/callouts/13.png delete mode 100644 doc/src/images/callouts/13.svg delete mode 100644 doc/src/images/callouts/14.png delete mode 100644 doc/src/images/callouts/14.svg delete mode 100644 doc/src/images/callouts/15.png delete mode 100644 doc/src/images/callouts/15.svg delete mode 100644 doc/src/images/callouts/16.svg delete mode 100644 doc/src/images/callouts/17.svg delete mode 100644 doc/src/images/callouts/18.svg delete mode 100644 doc/src/images/callouts/19.svg delete mode 100644 doc/src/images/callouts/2.png delete mode 100644 doc/src/images/callouts/2.svg delete mode 100644 doc/src/images/callouts/20.svg delete mode 100644 doc/src/images/callouts/21.svg delete mode 100644 doc/src/images/callouts/22.svg delete mode 100644 doc/src/images/callouts/23.svg delete mode 100644 doc/src/images/callouts/24.svg delete mode 100644 doc/src/images/callouts/25.svg delete mode 100644 doc/src/images/callouts/26.svg delete mode 100644 doc/src/images/callouts/27.svg delete mode 100644 doc/src/images/callouts/28.svg delete mode 100644 doc/src/images/callouts/29.svg delete mode 100644 doc/src/images/callouts/3.png delete mode 100644 doc/src/images/callouts/3.svg delete mode 100644 doc/src/images/callouts/30.svg delete mode 100644 doc/src/images/callouts/4.png delete mode 100644 doc/src/images/callouts/4.svg delete mode 100644 doc/src/images/callouts/5.png delete mode 100644 doc/src/images/callouts/5.svg delete mode 100644 doc/src/images/callouts/6.png delete mode 100644 doc/src/images/callouts/6.svg delete mode 100644 doc/src/images/callouts/7.png delete mode 100644 doc/src/images/callouts/7.svg delete mode 100644 doc/src/images/callouts/8.png delete mode 100644 doc/src/images/callouts/8.svg delete mode 100644 doc/src/images/callouts/9.png delete mode 100644 doc/src/images/callouts/9.svg delete mode 100644 doc/src/images/caution.png delete mode 100644 doc/src/images/caution.svg delete mode 100644 doc/src/images/draft.png delete mode 100644 doc/src/images/home.png delete mode 100644 doc/src/images/home.svg delete mode 100644 doc/src/images/important.png delete mode 100644 doc/src/images/important.svg delete mode 100644 doc/src/images/next.png delete mode 100644 doc/src/images/next.svg delete mode 100644 doc/src/images/next_disabled.png delete mode 100644 doc/src/images/note.png delete mode 100644 doc/src/images/note.svg delete mode 100644 doc/src/images/prev.png delete mode 100644 doc/src/images/prev.svg delete mode 100644 doc/src/images/prev_disabled.png delete mode 100644 doc/src/images/smiley.png delete mode 100644 doc/src/images/tip.png delete mode 100644 doc/src/images/tip.svg delete mode 100644 doc/src/images/toc-blank.png delete mode 100644 doc/src/images/toc-minus.png delete mode 100644 doc/src/images/toc-plus.png delete mode 100644 doc/src/images/up.png delete mode 100644 doc/src/images/up.svg delete mode 100644 doc/src/images/up_disabled.png delete mode 100644 doc/src/images/warning.png delete mode 100644 doc/src/images/warning.svg create mode 100644 examples/guide_axis_growing.cpp create mode 100644 examples/guide_fill_accumulator.cpp create mode 100644 examples/guide_fill_profile.cpp rename examples/{guide_access_bin_counts.cpp => guide_indexed_access.cpp} (81%) create mode 100755 tools/cov.sh delete mode 100644 tools/pass_on_fail.py delete mode 100644 tools/travis_install_boost.sh diff --git a/.gitignore b/.gitignore index a7680ffb..8c93f4af 100644 --- a/.gitignore +++ b/.gitignore @@ -3,11 +3,7 @@ doc/reference.xml *build* histogram.sublime-workspace CMakeSettings.json -doc/html/.buildinfo -doc/html/.doctrees -doc/html/.nojekyll -doc/html/objects.inv .DS_Store .vs* -test/*.xml.new -test/*.xml.new +*.info +tools/lcov-* diff --git a/.travis.yml b/.travis.yml index 3837412f..fb24b9f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,90 +1,96 @@ -# Copyright Hans Dembinski 2016-2017 -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) +# Use, modification, and distribution are +# 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) +# +# Copyright Antony Polukhin 2014-2019. +# Copyright Hans Dembinski 2019. + +# +# See https://svn.boost.org/trac/boost/wiki/TravisCoverals for description of the +# original file and how it can be used with Boost libraries. +# sudo: false language: cpp +os: linux -cache: - pip: true - directories: - - ${TRAVIS_BUILD_DIR}/deps/boost-1.66.0 +env: + global: + - if [ "$TRAVIS_BRANCH" == "master" ]; then + BRANCH=master; + else + BRANCH=develop; + fi -branches: - only: - - master - - develop + - LIBRARY_DIR=$(basename $TRAVIS_BUILD_DIR) -# g++-5 also needed for clang to see C++14 stdlib -addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - libstdc++-5-dev libgcc-5-dev libstdc++6 libasan2 libtsan0 libubsan0 + # Global options for sanitizers + # detect_leaks=0 is required on container builds by travis :( + - UBSAN_OPTIONS=print_stacktrace=1 + - LSAN_OPTIONS=verbosity=1:log_threads=1 + - ASAN_OPTIONS=detect_leaks=0:detect_stack_use_after_return=1 matrix: include: - - os: linux - compiler: clang - env: SERIAL=ON BENCH=OFF - os: osx - env: SERIAL=OFF BENCH=OFF - - os: linux # coverage build + script: + - ../../b2 -j2 -q cxxstd=14 test examples test//serial examples//serial + + # - name: "clang: minimal" + # addons: + # apt: + # sources: ubuntu-toolchain-r-test + # packages: libc++-dev + # script: + # - ./b2 -j2 -q toolset=clang cxxflags="-stdlib=libc++" linkflags="-lc++" libs/histogram + + - name: "gcc-5: ubasan" addons: apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-5 - env: - - MATRIX_EVAL="GCOV=gcov-5 && CC=gcc-5 && CXX=g++-5" + sources: ubuntu-toolchain-r-test + packages: g++-5 + script: + # ubsan+asan disabled in serial tests, because of bug in boost/serialization + - ../../b2 -j2 -q toolset=gcc-5 cxxstd=14 ubasan test examples && + ../../b2 -j2 -q toolset=gcc-5 cxxstd=14 test//serial examples//serial -git: - depth: 3 + - name: "gcc-7: coverage" + addons: + apt: + sources: ubuntu-toolchain-r-test + packages: g++-7 + script: + - ../../b2 -j2 -q toolset=gcc-7 coverage + test examples test//serial examples//serial + after_success: + - GCOV=gcov-7 tools/cov.sh -before_install: - - eval "${MATRIX_EVAL}" + - name: "gcc-8: ubasan, c++17" + addons: + apt: + sources: ubuntu-toolchain-r-test + packages: g++-8 + script: + # ubsan+asan disabled in serial tests, because of bug in boost/serialization + - ../../b2 -j2 -q toolset=gcc-8 cxxstd=17 ubasan test examples && + ../../b2 -j2 -q toolset=gcc-8 cxxstd=17 test//serial examples//serial -# install packages (pre-installed: pytest) -install: - - source tools/travis_install_boost.sh +before_script: + # Cloning minimal set of Boost libraries + - cd .. + - git clone -b $BRANCH --depth 10 https://github.com/boostorg/boost.git + - cd boost + - git submodule update --init --depth 10 tools/build tools/boostdep - - if [ -n "$GCOV" ]; then - pip install --user cpp-coveralls urllib3[secure]; - fi + # Replacing Boost module with this project and installing Boost dependencies + - rm -rf libs/$LIBRARY_DIR || true + - mv $TRAVIS_BUILD_DIR libs/$LIBRARY_DIR + - python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 2" $LIBRARY_DIR -# detect_leaks=0 is required on container builds by travis :( -script: - - mkdir build - - cd build - - if [ -n "$GCOV" ]; then - cmake .. -DBOOST_ROOT=${BOOST_DIR} - -DBUILD_BENCHMARKS=OFF - -DCMAKE_BUILD_TYPE=coverage && - make -j2 && - ctest -V; - else - cmake .. -DBOOST_ROOT=${BOOST_DIR} - -DTEST_SERIALIZATION=${SERIAL} - -DBUILD_BENCHMARKS=${BENCH} - -DCMAKE_BUILD_TYPE=Debug && - make -j2 && - LSAN_OPTIONS=verbosity=1:log_threads=1 ASAN_OPTIONS=detect_leaks=0:detect_stack_use_after_return=1 ctest -V; - fi - -# Calculate coverage -after_success: - if [ -n "$GCOV" ]; then - coveralls -r .. -b . --verbose --exclude ${TRAVIS_BUILD_DIR}/deps --gcov=`which ${GCOV}` --gcov-options '\-lpbc'; - fi - -# after_failure: - # - otool -L histogram.so - # - printf "r\nbt" > gdb.cmd - # - for x in *_test; do - # $x || gdb $x --batch -x gdb.cmd; - # done + # Adding missing toolsets and preparing Boost headers + - ./bootstrap.sh + - ./b2 headers + - cd libs/$LIBRARY_DIR notifications: email: false diff --git a/CMakeLists.txt b/CMakeLists.txt index 08985055..fa37c745 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,47 +104,18 @@ compiled_test(test/linearize_test.cpp) compiled_test(test/storage_adaptor_test.cpp) compiled_test(test/utility_test.cpp) -compiled_test(examples/getting_started_listing_01.cpp) -compiled_test(examples/getting_started_listing_02.cpp) -compiled_test(examples/getting_started_listing_03.cpp) -compiled_test(examples/guide_access_bin_counts.cpp) -compiled_test(examples/guide_axis_basic_demo.cpp) -compiled_test(examples/guide_axis_circular.cpp) -compiled_test(examples/guide_axis_with_labels.cpp) -compiled_test(examples/guide_axis_with_transform.cpp) -compiled_test(examples/guide_axis_with_uoflow_off.cpp) -compiled_test(examples/guide_custom_modified_axis.cpp) -compiled_test(examples/guide_custom_minimal_axis.cpp) -compiled_test(examples/guide_custom_2d_axis.cpp) -compiled_test(examples/guide_custom_storage.cpp) -compiled_test(examples/guide_custom_accumulators.cpp) -compiled_test(examples/guide_fill_histogram.cpp) -compiled_test(examples/guide_histogram_operators.cpp) -compiled_test(examples/guide_histogram_reduction.cpp) -compiled_test(examples/guide_histogram_streaming.cpp) -compiled_test(examples/guide_make_dynamic_histogram.cpp) -compiled_test(examples/guide_make_static_histogram.cpp) -compiled_test(examples/guide_parallel_filling.cpp) -compiled_test(examples/guide_stdlib_algorithms.cpp) - if (TEST_SERIALIZATION) - compiled_test(examples/guide_histogram_serialization.cpp Boost::serialization) - target_link_libraries(guide_histogram_serialization PRIVATE Boost::serialization) - compiled_test(test/unlimited_storage_serialization_test.cpp Boost::serialization) target_link_libraries(unlimited_storage_serialization_test PRIVATE Boost::serialization) compiled_test(test/storage_adaptor_serialization_test.cpp) target_link_libraries(storage_adaptor_serialization_test PRIVATE Boost::serialization) target_compile_definitions(storage_adaptor_serialization_test PRIVATE - -DVECTOR_INT_XML="${PROJECT_SOURCE_DIR}/test/storage_adaptor_serialization_test_vector_int.xml" - -DARRAY_UNSIGNED_XML="${PROJECT_SOURCE_DIR}/test/storage_adaptor_serialization_test_array_unsigned.xml" - -DMAP_DOUBLE_XML="${PROJECT_SOURCE_DIR}/test/storage_adaptor_serialization_test_map_double.xml") + -DXML_PATH="${PROJECT_SOURCE_DIR}/test/") compiled_test(test/histogram_serialization_test.cpp Boost::serialization) target_compile_definitions(histogram_serialization_test PRIVATE - -DSTATIC_XML="${PROJECT_SOURCE_DIR}/test/histogram_serialization_test_static.xml" - -DDYNAMIC_XML="${PROJECT_SOURCE_DIR}/test/histogram_serialization_test_dynamic.xml") + -DXML_PATH="${PROJECT_SOURCE_DIR}/test/") target_link_libraries(histogram_serialization_test PRIVATE Boost::serialization) endif() diff --git a/Jamfile b/Jamfile index 9500ec0e..123c4404 100644 --- a/Jamfile +++ b/Jamfile @@ -1,16 +1,37 @@ -# Copyright Klemens David Morgenstern, Hans P. Dembinski 2016-2017 # Copyright (c) 2018 Mateusz Loskot +# Copyright Klemens David Morgenstern, Hans P. Dembinski 2016-2017 # # 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 common ; +import testing ; +import ../config/checks/config : requires ; + +variant coverage : debug : + "--coverage" + "--coverage" + ; + +variant ubasan : debug : + "-fno-omit-frame-pointer -fsanitize=address,leak,undefined -fno-sanitize-recover=address,undefined" + # correct linkflags don't work on travis, use workaround + # "-fsanitize=address,leak,undefined" + "-lasan -lubsan" + ; + project - : - requirements - gcc:"-std=c++14 -Wall -Wextra -Wno-noexcept-type" - clang:"-std=c++14 -Wall -Wextra" - darwin:"-std=c++14 -Wall -Wextra" + : requirements + [ requires + cxx14_constexpr cxx14_decltype_auto cxx14_generic_lambdas cxx14_return_type_deduction cxx11_user_defined_literals + # list could go on... + ] + /boost//headers + multi + : default-build + all + #on ; build-project test ; diff --git a/README.md b/README.md index 6e21cba6..3bf25355 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Coded with ❤. Powered by the [Boost community](https://www.boost.org) and the Branch | Linux [1] and OSX [2] | Windows [3] | Coverage ------- | --------------------- |------------ | -------- -develop | [![Build Status Travis](https://travis-ci.com/HDembinski/histogram.svg?branch=develop)](https://travis-ci.com/HDembinski/histogram?branch=develop) | [![Build status](https://ci.appveyor.com/api/projects/status/400lx25l3jdpk96b/branch/develop?svg=true)](https://ci.appveyor.com/project/HDembinski/histogram/branch/develop) | [![Coverage Status](https://coveralls.io/repos/github/HDembinski/histogram/badge.svg?branch=develop)](https://coveralls.io/github/HDembinski/histogram?branch=develop) +develop | [![Build Status Travis](https://travis-ci.com/HDembinski/histogram.svg?branch=develop)](https://travis-ci.com/HDembinski/histogram?branch=develop) | [![Build status](https://ci.appveyor.com/api/projects/status/400lx25l3jdpk96b/branch/develop?svg=true)](https://ci.appveyor.com/project/HDembinski/histogram/branch/develop) | [![codecov](https://codecov.io/gh/HDembinski/histogram/branch/develop/graph/badge.svg)](https://codecov.io/gh/HDembinski/histogram) @@ -39,7 +39,7 @@ Check out the [full documentation](http://hdembinski.github.io/histogram/doc/htm * Support for programming with units (4) * Optional serialization based on [Boost.Serialization](https://www.boost.org/doc/libs/release/libs/serialization/) -1. In the standard configuration, if you don't use weighted increments. The counter capacity is increased dynamically as the cell counts grow. When even the largest plain integral type would overflow, the storage switches to a [Boost.Multiprecision](https://www.boost.org/doc/libs/release/libs/multiprecision/) integer, which is only limited by available memory. +1. In the standard configuration, if you don't use weighted increments. The counter capacity is increased dynamically as the cell counts grow. When even the largest plain integral type would overflow, the storage switches to a multiprecision integer similar to those in [Boost.Multiprecision](https://www.boost.org/doc/libs/release/libs/multiprecision/), which is only limited by available memory. 2. An axis can be configured to grow when a value is encountered that is outside of its range. It then grows new bins towards this value so that the value ends up in the new highest or lowest bin. 3. The histogram can be configured to hold an arbitrary accumulator in each cell instead of a simple counter. Extra values can be passed to the histogram, for example, to compute the mean and variance of values which fall into the same cell. This can be used to compute variance estimates for each cell. These are useful when histograms are to be compared quantitatively and if a statistical model is fitted to the cell values. 4. Builtin axis types can configured to only accept dimensional quantities, like those from [Boost.Units](https://www.boost.org/doc/libs/release/libs/units/). This means you get an error if you try to fill a length when the histogram axis expects a time, for example. diff --git a/benchmark/speed_root.cpp b/benchmark/speed_root.cpp index 1c0abb88..8c58702e 100644 --- a/benchmark/speed_root.cpp +++ b/benchmark/speed_root.cpp @@ -67,8 +67,6 @@ double compare_3d(unsigned n, int distrib) { return t; } -#include - double compare_6d(unsigned n, int distrib) { auto r = random_array(n, distrib); int bin[] = {10, 10, 10, 10, 10, 10}; @@ -76,7 +74,7 @@ double compare_6d(unsigned n, int distrib) { double max[] = {1, 1, 1, 1, 1, 1}; THnI h("", "", 6, bin, min, max); double t = clock(); - for (auto it = r.get(), end = r.get() + n; it != end; it += 6) { h.Fill(it); } + for (auto it = r.get(), end = r.get() + n; it != end; it += 6) h.Fill(it); t = (double(clock()) - t) / CLOCKS_PER_SEC / n * 1e9; TH1D* h1 = h.Projection(0); assert(distrib != 0 || h1->GetSumOfWeights() == n / 6); diff --git a/doc/guide.qbk b/doc/guide.qbk index 210f3ae9..ba7a1631 100644 --- a/doc/guide.qbk +++ b/doc/guide.qbk @@ -13,13 +13,13 @@ Use the convenient factory function [funcref boost::histogram::make_histogram ma An axis object defines how input values are mapped to bins, which means that it defines the number of bins along that axis and a mapping function from input values to bins. If you provide one axis, the histogram is one-dimensional. If you provide two, it is two-dimensional, and so on. -In the example above, the compiler knows the number of axes and their type at compile-time, the information can be deduced from the arguments to [funcref boost::histogram::make_histogram make_histogram]. This gives you the best performance, but sometimes you only know the axis configuration at run-time, usually because it depends on run-time user input. You can also create a sequence of axes at run-time and pass them to an overload of the factory function. Here is an example. +In the example above, the compiler knows the number of axes and their type at compile-time, the information can be deduced from the arguments to [funcref boost::histogram::make_histogram make_histogram]. This gives the best performance, but sometimes you only know the axis configuration at run-time, because it depends on information that's only available at run-time. So you can also create axes at run-time and pass them to an overload of the [funcref boost::histogram::make_histogram make_histogram] function. Here is an example. [import ../examples/guide_make_dynamic_histogram.cpp] [guide_make_dynamic_histogram] [note -When the axis types are known at compile-time, the histogram stores them in a `std::tuple`. If they are only known at run-time, it uses a `std::vector`. In almost all ways, the two versions of the histogram act identically, except that the compile-time version is faster. The [link histogram.overview.rationale.structure.host rationale] has more details on this point. +When the axis types are known at compile-time, the histogram internally holds them in a `std::tuple`, which is very efficient and avoids a memory allocation from the heap. If they are only known at run-time, it stores the axes in a `std::vector`. The interface hides this difference, but not perfectly. There are a corner cases where the difference becomes apparent. The [link histogram.overview.rationale.structure.host rationale] has more details on this point. ] The factory function [funcref boost::histogram::make_histogram make_histogram] uses the default storage type, which provides safe counting, is fast, and memory efficient. If you want to create a histogram with another storage type, use [funcref boost::histogram::make_histogram_with make_histogram_with]. To learn more about other storage types and how to create your own, have a look at the section [link histogram.guide.expert Advanced Usage]. @@ -155,7 +155,19 @@ A circular axis cannot have an underflow bin, passing both options together gene [*Growing axes] -To-do. +Each builtin axis has an option to make it grow beyond its initial range when a value outside of that range is discovered, instead of counting this value in the under- or overflow bins (or to discard it). This can be incredibly convenient. Example: + +[import ../examples/guide_axis_growing.cpp] +[guide_axis_growing] + +So this feature is very convenient, but before you use it all the time, keep two caveats in mind. + +* Growing axes come with a run-time cost, since the histogram has to reallocate memory + for all cells when any axis size changes. Whether this performance hit is noticeable depends on your application. This is a minor issue. +* If you have unexpected outliers in your data which are far away from the normal range, + the axis could grow to a huge size and the corresponding huge memory request could bring your computer to its knees. This can be a major issue, and it is the reason why growing axis are not the default. + +A growing axis can have under- and overflow bins, but these only count the special floating point values +-infinity and NaN. [endsect] [/ options] @@ -167,33 +179,37 @@ To-do. [section Fill a histogram] -After you created a histogram, you want to insert tuples of possibly multi-dimensional and values of different types. This is done with the flexible `operator()` call, which you typically do in a loop. Some extra parameters can be passed to the method as shown in the next example. +After you created a histogram, you want to insert tuples of possibly multi-dimensional and values of different types. This is done with the flexible `operator()` call, which you typically use in a loop. After the histogram has been filled, you want to access the counts per bin at some point. To access each bin, you use a multi-dimensional index, which consists of a sequence of bin indices for each axis in order. Example: [import ../examples/guide_fill_histogram.cpp] [guide_fill_histogram] -`operator()` either takes `N` arguments or a container with `N` elements, where `N` is equal to the number of axes of the histogram. It finds the corresponding bin, and increments the bin counter by one. +`operator()` either takes `N` arguments or a container with `N` elements, where `N` is equal to the number of axes of the histogram. It finds the corresponding bin for the input and increments the bin counter by one. -`operator()(weight(x), ...)` does the same as the first call, but increments the bin counter by the value `x`. The type of `x` is not restricted, usually it is a real number. The `weight(x)` helper class must be first argument. You can freely mix calls with and without a `weight`. Calls without a `weight` act like the weight is `1`. +`operator()(..., weight(w))` or `operator()(weight(w), ...)` does the same, but increments the bin counter by the value `w`, which may be an integer or floating point type. The helper function `weight()` just marks this argument as a weight, so that it can be distinguished from the other inputs. It may be the first or last argument. You can freely mix calls with and without a `weight`. Calls without `weight` act like the weight is `1`. Why weighted increments are sometimes useful is explained [link histogram.overview.rationale.weights in the rationale]. -Why weighted increments are sometimes useful, especially in a scientific context, is explained [link histogram.overview.rationale.weights in the rationale]. If you don't see the point, you can just ignore this type of call. This feature does not affect the performance of the histogram if you don't use it. +[note The default storage loses its no-overflow-guarantee when you pass floating point weights, but maintains it for integer weights.] -[note The first call to a weighted fill internally switches the default storage from integral counters to another type, which holds two real numbers per bin, one for the sum of weights (the weighted count), and another for the sum of weights squared (the variance of the weighted count). This is not necessary for unweighted fills, because the two sums are identical is all weights are `1`. The default storage automatically optimizes this case by using only one integral number per bin as long as no weights are encountered.] +The method `histogram::at(...)` (in analogy to `std::vector::at`). It accepts integral indices, one for each axis of the histogram, and returns the cell value. + +If you want to iterate over all cells, use the [funcref boost::histogram::indexed indexed] range generator, which is convenient and faster than a naive for loop: + +[import ../examples/guide_indexed_access.cpp] +[guide_indexed_access] [endsect] -[section Access bin counts] +[section Fill a profile or any histogram with accumulators] -After the histogram has been filled, you want to access the counts per bin at some point. You may want to visualize the counts, or compute some quantities like the mean from the data distribution approximated by the histogram. +You can do more than just counting with this library. Histogram cells can be filled with arbitrary accumulators which may accept a sample. When the accumulator computes the mean of the samples, the data structure is called a /profile/. Profiles can be generated with the factory function [boost::histogram::make_profile make_profile]. Example: -To access each bin, you use a multi-dimensional index, which consists of a sequence of bin indices for each axis in order. You can use this index to access the value for each and the variance estimate, using the method `histogram::at(...)` (in analogy to `std::vector::at`). It accepts integral indices, one for each axis of the histogram, and returns the associated bin counter type. The bin counter type then allows you to access the count value and its variance. +[import ../examples/guide_fill_profile.cpp] +[guide_fill_profile] -The calls are demonstrated in the next example. +Just like `weight()`, `sample()` is a marker function. And like `weight()`, it must be the first or last argument. Accumulators may accept more than a single sample value, and they may also accept a weight. Example: -[import ../examples/guide_access_bin_counts.cpp] -[guide_access_bin_counts] - -[note The numbers returned by `value()` and `variance()` are always equal, if weighted fills are not used. The internal structure, which handles the bin counters, has been optimised for this common case. Internally only a single integral number per bin is used until a weighted fill, then the counters internally switch to storing two real numbers per bin. If the very first call to `histogram(...)` is already a weighted increment, the two real numbers per bin are allocated directly without any superfluous conversion from integral counters to double counters. This special case is efficiently handled.] +[import ../examples/guide_fill_accumulator.cpp] +[guide_fill_accumulator] [endsect] diff --git a/doc/rationale.qbk b/doc/rationale.qbk index 01b0718d..33e48902 100644 --- a/doc/rationale.qbk +++ b/doc/rationale.qbk @@ -86,7 +86,7 @@ The default storage therefore starts with a minimum amount of memory per cell, i [$../storage_3_uint64.svg] -When even that is not enough, the default storage switches to the [@boost:/libs/multiprecision/index.html Boost.Multiprecision] type `cpp_int`, whose capacity is limited only by available memory. The following image is not to scale: +When even that is not enough, the default storage switches to a multiprecision type similar to those in [@boost:/libs/multiprecision/index.html Boost.Multiprecision], whose capacity is limited only by available memory. The following image is not to scale: [$../storage_3_cpp_int.svg] diff --git a/doc/src/boostbook.css b/doc/src/boostbook.css deleted file mode 100644 index 28f89359..00000000 --- a/doc/src/boostbook.css +++ /dev/null @@ -1,716 +0,0 @@ - -/*============================================================================= -Copyright (c) 2004 Joel de Guzman -http://spirit.sourceforge.net/ - -Copyright 2013 Niall Douglas additions for colors and alignment. -Copyright 2013 Paul A. Bristow additions for more colors and alignments. - -Distributed under the Boost Software License, Version 1.0. (See accompany- -ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -=============================================================================*/ - -/*============================================================================= -Body defaults -=============================================================================*/ - - body - { - margin: 1em; - font-family: sans-serif; - } - -/*============================================================================= -Paragraphs -=============================================================================*/ - - p - { - text-align: left; - font-size: 10pt; - line-height: 1.15; - } - -/*============================================================================= -Program listings -=============================================================================*/ - - /* Code on paragraphs */ - p tt.computeroutput - { - font-size: 9pt; - } - - pre.synopsis - { - font-size: 9pt; - margin: 1pc 4% 0pc 4%; - padding: 0.5pc 0.5pc 0.5pc 0.5pc; - } - - .programlisting, - .screen - { - font-size: 9pt; - display: block; - margin: 1pc 4% 0pc 4%; - padding: 0.5pc 0.5pc 0.5pc 0.5pc; - } - - /* Program listings in tables don't get borders */ - td .programlisting, - td .screen - { - margin: 0pc 0pc 0pc 0pc; - padding: 0pc 0pc 0pc 0pc; - } - -/*============================================================================= -Headings -=============================================================================*/ - - h1, h2, h3, h4, h5, h6 - { - text-align: left; - margin: 1em 0em 0.5em 0em; - font-weight: bold; - } - - h1 { font-size: 140%; } - h2 { font-weight: bold; font-size: 140%; } - h3 { font-weight: bold; font-size: 130%; } - h4 { font-weight: bold; font-size: 120%; } - h5 { font-weight: normal; font-style: italic; font-size: 110%; } - h6 { font-weight: normal; font-style: italic; font-size: 100%; } - - /* Top page titles */ - title, - h1.title, - h2.title - h3.title, - h4.title, - h5.title, - h6.title, - .refentrytitle - { - font-weight: bold; - margin-bottom: 1pc; - } - - h1.title { font-size: 140% } - h2.title { font-size: 140% } - h3.title { font-size: 130% } - h4.title { font-size: 120% } - h5.title { font-size: 110% } - h6.title { font-size: 100% } - - .section h1 - { - margin: 0em 0em 0.5em 0em; - font-size: 140%; - } - - .section h2 { font-size: 140% } - .section h3 { font-size: 130% } - .section h4 { font-size: 120% } - .section h5 { font-size: 110% } - .section h6 { font-size: 100% } - - /* Code on titles */ - h1 tt.computeroutput { font-size: 140% } - h2 tt.computeroutput { font-size: 140% } - h3 tt.computeroutput { font-size: 130% } - h4 tt.computeroutput { font-size: 130% } - h5 tt.computeroutput { font-size: 130% } - h6 tt.computeroutput { font-size: 130% } - - -/*============================================================================= -Author -=============================================================================*/ - - h3.author - { - font-size: 100% - } - -/*============================================================================= -Lists -=============================================================================*/ - - li - { - font-size: 10pt; - line-height: 1.3; - } - - /* Unordered lists */ - ul - { - text-align: left; - } - - /* Ordered lists */ - ol - { - text-align: left; - } - -/*============================================================================= -Links -=============================================================================*/ - - a - { - text-decoration: none; /* no underline */ - } - - a:hover - { - text-decoration: underline; - } - -/*============================================================================= -Spirit style navigation -=============================================================================*/ - - .spirit-nav - { - text-align: right; - } - - .spirit-nav a - { - color: white; - padding-left: 0.5em; - } - - .spirit-nav img - { - border-width: 0px; - } - -/*============================================================================= -Copyright footer -=============================================================================*/ - .copyright-footer - { - text-align: right; - font-size: 70%; - } - - .copyright-footer p - { - text-align: right; - font-size: 80%; - } - -/*============================================================================= -Table of contents -=============================================================================*/ - - div.toc - { - margin: 1pc 4% 0pc 4%; - padding: 0.1pc 1pc 0.1pc 1pc; - font-size: 80%; - line-height: 1.15; - } - - .boost-toc - { - float: right; - padding: 0.5pc; - } - - /* Code on toc */ - .toc .computeroutput { font-size: 120% } - - /* No margin on nested menus */ - - .toc dl dl { margin: 0; } - -/*============================================================================= -Tables -=============================================================================*/ - - .table-title, - div.table p.title - { - margin-left: 4%; - padding-right: 0.5em; - padding-left: 0.5em; - } - - .informaltable table, - .table table - { - width: 92%; - margin-left: 4%; - margin-right: 4%; - } - - div.informaltable table, - div.table table - { - padding: 4px; - } - - /* Table Cells */ - div.informaltable table tr td, - div.table table tr td - { - padding: 0.5em; - text-align: left; - font-size: 9pt; - } - - div.informaltable table tr th, - div.table table tr th - { - padding: 0.5em 0.5em 0.5em 0.5em; - border: 1pt solid white; - font-size: 80%; - } - - table.simplelist - { - width: auto !important; - margin: 0em !important; - padding: 0em !important; - border: none !important; - } - table.simplelist td - { - margin: 0em !important; - padding: 0em !important; - text-align: left !important; - font-size: 9pt !important; - border: none !important; - } - -/*============================================================================= -Suppress margins in tables -=============================================================================*/ - - table th > *:first-child, - table td > *:first-child - { - margin-top: 0; - } - - table th > *:last-child, - table td > *:last-child - { - margin-bottom: 0; - } - -/*============================================================================= -Blurbs -=============================================================================*/ - - div.note, - div.tip, - div.important, - div.caution, - div.warning, - p.blurb - { - font-size: 9pt; /* A little bit smaller than the main text */ - line-height: 1.2; - display: block; - margin: 1pc 4% 0pc 4%; - padding: 0.5pc 0.5pc 0.5pc 0.5pc; - } - - p.blurb img - { - padding: 1pt; - } - -/*============================================================================= -Variable Lists -=============================================================================*/ - - div.variablelist - { - margin: 1em 0; - } - - /* Make the terms in definition lists bold */ - div.variablelist dl dt, - span.term - { - font-weight: bold; - font-size: 10pt; - } - - div.variablelist table tbody tr td - { - text-align: left; - vertical-align: top; - padding: 0em 2em 0em 0em; - font-size: 10pt; - margin: 0em 0em 0.5em 0em; - line-height: 1; - } - - div.variablelist dl dt - { - margin-bottom: 0.2em; - } - - div.variablelist dl dd - { - margin: 0em 0em 0.5em 2em; - font-size: 10pt; - } - - div.variablelist table tbody tr td p, - div.variablelist dl dd p - { - margin: 0em 0em 0.5em 0em; - line-height: 1; - } - -/*============================================================================= -Misc -=============================================================================*/ - - /* Title of books and articles in bibliographies */ - span.title - { - font-style: italic; - } - - span.underline - { - text-decoration: underline; - } - - span.strikethrough - { - text-decoration: line-through; - } - - /* Copyright, Legal Notice */ - div div.legalnotice p - { - text-align: left - } - -/*============================================================================= -Colors -=============================================================================*/ - - @media screen - { - body { - background-color: #FFFFFF; - color: #000000; - } - - /* Syntax Highlighting */ - .keyword { color: #0000AA; } - .identifier { color: #000000; } - .special { color: #707070; } - .preprocessor { color: #402080; } - .char { color: teal; } - .comment { color: #800000; } - .string { color: teal; } - .number { color: teal; } - .white_bkd { background-color: #FFFFFF; } - .dk_grey_bkd { background-color: #999999; } - - /* Links */ - a, a .keyword, a .identifier, a .special, a .preprocessor - a .char, a .comment, a .string, a .number - { - color: #005a9c; - } - - a:visited, a:visited .keyword, a:visited .identifier, - a:visited .special, a:visited .preprocessor a:visited .char, - a:visited .comment, a:visited .string, a:visited .number - { - color: #9c5a9c; - } - - h1 a, h2 a, h3 a, h4 a, h5 a, h6 a, - h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover, - h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited - { - text-decoration: none; /* no underline */ - color: #000000; - } - - /* Copyright, Legal Notice */ - .copyright - { - color: #666666; - font-size: small; - } - - div div.legalnotice p - { - color: #666666; - } - - /* Program listing */ - pre.synopsis - { - border: 1px solid #DCDCDC; - } - - .programlisting, - .screen - { - border: 1px solid #DCDCDC; - } - - td .programlisting, - td .screen - { - border: 0px solid #DCDCDC; - } - - /* Blurbs */ - div.note, - div.tip, - div.important, - div.caution, - div.warning, - p.blurb - { - border: 1px solid #DCDCDC; - } - - /* Table of contents */ - div.toc - { - border: 1px solid #DCDCDC; - } - - /* Tables */ - div.informaltable table tr td, - div.table table tr td - { - border: 1px solid #DCDCDC; - } - - div.informaltable table tr th, - div.table table tr th - { - background-color: #F0F0F0; - border: 1px solid #DCDCDC; - } - - .copyright-footer - { - color: #8F8F8F; - } - - /* Misc */ - span.highlight - { - color: #00A000; - } - } - - @media print - { - /* Links */ - a - { - color: black; - } - - a:visited - { - color: black; - } - - .spirit-nav - { - display: none; - } - - /* Program listing */ - pre.synopsis - { - border: 1px solid gray; - } - - .programlisting, - .screen - { - border: 1px solid gray; - } - - td .programlisting, - td .screen - { - border: 0px solid #DCDCDC; - } - - /* Table of contents */ - div.toc - { - border: 1px solid gray; - } - - .informaltable table, - .table table - { - border: 1px solid gray; - border-collapse: collapse; - } - - /* Tables */ - div.informaltable table tr td, - div.table table tr td - { - border: 1px solid gray; - } - - div.informaltable table tr th, - div.table table tr th - { - border: 1px solid gray; - } - - table.simplelist tr td - { - border: none !important; - } - - /* Misc */ - span.highlight - { - font-weight: bold; - } - } - -/*============================================================================= -Images -=============================================================================*/ - - span.inlinemediaobject img - { - vertical-align: middle; - } - -/*============================================================================== -Super and Subscript: style so that line spacing isn't effected, see -http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=1&postId=5341 -==============================================================================*/ - -sup, -sub { -height: 0; -line-height: 1; -vertical-align: baseline; -position: relative; - -} - -/* For internet explorer: */ - -* html sup, -* html sub { -vertical-align: bottom; -} - -sup { -bottom: 1ex; -} - -sub { -top: .5ex; -} - -/*============================================================================== -Indexes: pretty much the same as the TOC. -==============================================================================*/ - - .index - { - font-size: 80%; - padding-top: 0px; - padding-bottom: 0px; - margin-top: 0px; - margin-bottom: 0px; - margin-left: 0px; - } - - .index ul - { - padding-left: 3em; - } - - .index p - { - padding: 2px; - margin: 2px; - } - - .index-entry-level-0 - { - font-weight: bold; - } - - .index em - { - font-weight: bold; - } - - -/*============================================================================== -Alignment and coloring use 'role' feature, available from Quickbook 1.6 up. -Added from Niall Douglas for role color and alignment. -http://article.gmane.org/gmane.comp.lib.boost.devel/243318 -*/ - -/* Add text alignment (see http://www.w3schools.com/cssref/pr_text_text-align.asp) */ -span.aligncenter -{ - display: inline-block; width: 100%; text-align: center; -} -span.alignright -{ - display: inline-block; width: 100%; text-align: right; -} -/* alignleft is the default. */ -span.alignleft -{ - display: inline-block; width: 100%; text-align: left; -} - -/* alignjustify stretches the word spacing so that each line has equal width -within a chosen fraction of page width (here arbitrarily 20%). -*Not* useful inside table items as the column width remains the total string width. -Nor very useful, except to temporarily restrict the width. -*/ -span.alignjustify -{ - display: inline-block; width: 20%; text-align: justify; -} - -/* Text colors. -Names at http://www.w3.org/TR/2002/WD-css3-color-20020219/ 4.3. X11 color keywords. -Quickbook Usage: [role red Some red text] - -*/ -span.red { inline-block; color: red; } -span.green { color: green; } -span.lime { color: #00FF00; } -span.blue { color: blue; } -span.navy { color: navy; } -span.yellow { color: yellow; } -span.magenta { color: magenta; } -span.indigo { color: #4B0082; } -span.cyan { color: cyan; } -span.purple { color: purple; } -span.gold { color: gold; } -span.silver { color: silver; } /* lighter gray */ -span.gray { color: #808080; } /* light gray */ diff --git a/doc/src/images/alert.png b/doc/src/images/alert.png deleted file mode 100644 index b4645bc7e7cd81f2818bf22aa898e95f89f7b154..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 603 zcmeAS@N?(olHy`uVBq!ia0y~yV31^BU=ZVAW?*1oN<7}ez`(#Bl2vQw%VQUVy#($c(b7<_!Z&&*`7 zwYIFTuIA!kP?6(!`t<3^g$y0J3{Q73WQH(YSjJ#(AQj-}VXe>LZ_gkv$q?hiVP&Xj ztS4or%^)MjpsB?1|Nnp9pi5p13=F0vL4Lvi$p8#BTQ7jZgtNdSvY3H^>jMZgI;}C8 z!N9FSxfgB=H7N+NC77H_+N#nawR{=RqTMBX)(LXL|IjinhDSdCyWWZ3S$0kBOZbahGm>{cU3L4X z*xaKNrl+L*2&>`tT{GF}sK6TCoSy58@94C>csZ@3se0z)OD!J`ePg?KNk!eRu!nuZ zwIuy5g5`UyU*2!`JMiPV^UIVvmW1t{f1*^~1#9h_jDIZO*R6JmbN8&QBXd?)zY=(& z`HG+Mis#k2-hNM1nwI_8efYU@yAuCZhY42|Be;Juo!svFUA16}A_D^hgQu&X%Q~lo FCIA+53ZVc1 diff --git a/doc/src/images/blank.png b/doc/src/images/blank.png deleted file mode 100644 index 764bf4f0c3bb4a09960b04b6fa9c9024bca703bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 374 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 diff --git a/doc/src/images/callouts/1.png b/doc/src/images/callouts/1.png deleted file mode 100644 index 6003ad3af44ecde89a963d5af6a4180217319dfb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 391 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`*F|>EaktF{gKeVcsDJ z0oVU;*6~a;Smx2ZrsEQ?ZxM&ygvBnFE?nmtg94rky>!~x8m)3j$<^(USQPg)>&zq; zMi;kRX=V2=&tIr>`d!)XyUpL@9=UmHetuZ+!_#HmOU>-J$pS3-bN!ardIyAF-G1#? z>&)f7E`k#|4sWoP;JM|(l6I_WZ`%~1y>agujE%b%?TB9+mb}(fsxyPFgQGMy*=%;A z(aZyu>`GQPiY$*T-1gu1pAwY3_N%b5cB#xoiRPn8jf*q{Trb|_a%sui&dtzin6_r? zu}%d~p(mAmOGTO#c2u;xJ(}Y^?ex>t7XL(?7U+1p1hOa|ab;w%c)sCoo@_(^WX<=s zr#89B91nl^w~jx#=XQ?S<*?OXYm`>JmO9g8;`^U+STt2<{M7jt yFTo&UT%Db3I{*CoWB+`guig6oxB - - - -]> - - - - - - - - diff --git a/doc/src/images/callouts/10.png b/doc/src/images/callouts/10.png deleted file mode 100644 index 0426f516a497db7f9a989ae412c381123c882a59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 485 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`(f1)5S5QVovKM!_~JE zMB47_a|Rw%VTn}{6Ibo_{>?on>HF_suX>mE-_|+p)}_VbyG%XWRxDs!Bbdb`rSkCf z_opQpQ)e&z9?Q3;X^2drllMU70&71c8CwuJm{abIp zeHPuYNTZJ3@x#oHxOW1*hRe1@t$mhYkYRMp!NudU$f{L`HtEbcpPpkT-Q%WwW82?% zC04fVjt$l>J1E5m&cv;Mo-ym249h`b!OT;yI|^kU z7g#)~+Iz@=rzNo?Z+rL2lqSFB&0ni{FPmfwyfr;gD5K)Z38R1FYejhuGSfQP|hTIvQJ?m5M8zE|_KJ2Ny0Fm1o>%kU%6J0MhalaBNL z`|XP~Ht29?&a!*3EqAew_mM&!z3HdD7hn7l!t9~x=u!|XzH8m#&o*bC7c(?GuT1E< zIxY74U)KBI?en(Zj`8vg@_IC9@{~!dRw-$!in=2h%i uo%h^T#Pz@K#3`Fjeg5 - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/11.png b/doc/src/images/callouts/11.png deleted file mode 100644 index 821afc4fa84787cc97485b71e9f2078f45c93dca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`&U3>EaktF{gFX#;)5A z0&V{%irr-ME}D3(<3UjG?A^;f=DTxNc8JvRJ?~omN$9208L_ft0gE{24F|>2&Q_(X zyZRk}S@Y!IJLwtuX$cuSW9kad-E9>}+B4ar@B8JKU&IA}ZdvzvdHazWz|5Z1g ze)`Eh`){a=Ty&?>q6`CxFY1#$=XWS5S;+8pJeF8|am8VmFNNE0pWSjTLp3m4UCF?B z)v7}^cJ1H)wSBfZUSXp*CCGT~*L1 z!O^woK;8cKATG~IcM5iAPD}l8PyF`VZ_(}ou7b0cInG+vv8ev~-ZX{}_a4{SRWsNx zp57$DG;5jTyyy8w3^D7&C6fPqtf+bOwJP3 - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/12.png b/doc/src/images/callouts/12.png deleted file mode 100644 index 7cec72720fa9bb6f49fc4b405f7e36f20abe7fbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 488 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`(fP)5S5QVovKM+tara zMB3h~S9S>cC`GVy&NA$7e!FZ3*ZX_(gMKMn{jgqg*t>n5-mVwdc+LxmI|e9UlrZu5 zQ({_ROHtjRNV$1z%lk=bT+YJ`-QVnLY|jT_oBf)`qRPnx(gN%Xx|4tEMdaVwoi3 z8lgAcLau*<4)^ratatOor+TqI{wNVS?clathJwW!uZ)j$%&5q+Ew{P&-MZ_q|3(_ifRH$!b{%@XfPPgvO) wR!x~yId8sr_tEzopr0G&e8k^lez diff --git a/doc/src/images/callouts/12.svg b/doc/src/images/callouts/12.svg deleted file mode 100644 index 9794044c..00000000 --- a/doc/src/images/callouts/12.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/13.png b/doc/src/images/callouts/13.png deleted file mode 100644 index 5b41e02a670f020ae62b7854482c4ba1980d73cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 509 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`%IK)5S5QVovKN`}4B` zMA$w&XL9s;aOlF(1%)YvneO4jm-o(&U;MKD#e?Mq8+>b)^R3G((>5$`ILflv=tsMT zqri^uWh?XJrteF)Ir(#L@uYSZ#}5m2PWL-;h`yh)YSr?%_21hCg6ylJ<~^TZ68k@M z*0PUs0U}2m4Zrz%{ru!$;?!{|$E-JRd$xd+!qOu@YuZ+=+K?-K{IOu7#Gy?(C029K zJuHwgKK8+3O1mEi<8zsP?~|?OE?SqZ;@R}Hh*OcJN#Q`=cIVYsi%fl`jgRf~&@_Gf zwzE(sdH3B%ReKL@(z)}#{LAm!8Ou74CNVNBn8MT`ef;AL!#4E;rLlAT)H7zW#a>U8 zU^AP|o3>d}=J>$`0|rHwDM43C-@g0)`~9hChd_}fnOvtgEzsbyc%HHSwnVR+$0Qaf z4hDzV>nAp?Vf*l#Q@}~VH~7Z3-c_p%=AWOKD!ECAd8tU(q6Mq8jughk>rJ2Tw)o@M zm#pV3mrVI!!@p|Pp+XrSHQ@j+Lm56tj!LO-Hu>!LzuT|B{(4Tap5^mRI^HKOr#o>( zhECmcH*b>$SLC#%J&RUEtqrq3WKa^{tg=+3a-Mjg$X|1pImHv7|6G6l?EhE#0)GDv Vq@B#jVqjok@O1TaS?83{1OO3{ - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/14.png b/doc/src/images/callouts/14.png deleted file mode 100644 index de5bdbd3eb8be01d27b6f1a345d586d0c4d61b2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 499 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`(f6)5S5QVovL&ji+t} zh_HY7zn8PK$&+QbhfZH4OXk6oR~J^xFa4ru^@GK(LHCDmEpzN0DV1hDCj-+7ZjQ+v zYTxf&UV7^JrT0DT=ibj@uHP27{{Ga|pN^VKANF1{d3)jY*E+*vNA@lkcl~(Lphv#f zZSgm;g1vG7SsXu1?TCBVaZcj#*Q&kO-j-$e7zzmX9alE-b>4iFg+V~@k_l_W_wBcH zWmp*BaqNHHW9Xsz@VDKv%bG0$2|bO5Z6>~kGkrGPetRKrdu;6W&)@+-S^-5e@qWpx=%~ppu-*HbtcU?B((KtQse2TO*ZEl8Jswt zRO&J4%x73CvPq};vBd=w-op^F6<=oH98=hD0fB5^~^0#Ht9-5wBo~e - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/15.png b/doc/src/images/callouts/15.png deleted file mode 100644 index 3fd6ac38603390bf6f9bbfdb85ddb203e2edc421..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 507 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`%IO)5S5QVovL&-F>$L z1lS(@e{k6MP=#(Q)65P&Df1-{87Bltt+Mf&((ZAvc!Ef@>!Js&9H9b5iNOkrjBYL6 zJ*_!sB>iV?h@ACiit<@=<+J)R*K4P%cxw9w^X5-kmdSp5TRo@ZmA&eVHGWMv{dC`S zuce2g9b}I0mp%UT(3$h)E?kO6N0T-NtiR6f#9?6EcU;-Tw>eSb#{2IdZ1@=hR$sjr zzyA8Z#}+%3XYST(VGvBTnww-G;h@R7RHW^&qTY1wDM1E2%vZCnP73-ad;I5-GeP_8 zE`G0F6Q(`qeEN%Bd`m@QuDc4b82Acr%ROx3%dny5{(I}bX7&S{bY%G0Jv1kte!3xU z{l(W`FJx^snCW9M|9s%ekN~~u3#V){n|<~=yTas?3Ovp)cJVPNC~di&>!G - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/16.svg b/doc/src/images/callouts/16.svg deleted file mode 100644 index 01d6bf81..00000000 --- a/doc/src/images/callouts/16.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/17.svg b/doc/src/images/callouts/17.svg deleted file mode 100644 index 0a04c556..00000000 --- a/doc/src/images/callouts/17.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/18.svg b/doc/src/images/callouts/18.svg deleted file mode 100644 index 1cb891b3..00000000 --- a/doc/src/images/callouts/18.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/19.svg b/doc/src/images/callouts/19.svg deleted file mode 100644 index e6fbb179..00000000 --- a/doc/src/images/callouts/19.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/2.png b/doc/src/images/callouts/2.png deleted file mode 100644 index f7c1578846cd7e67f148e7bbe3178ec170050e48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 446 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`)q*>EaktF{gFH!7eFB zfwuoy?SYP89?67Uc^u>7$ueKD;_TuU8yCKP?%y^nk6}6Q`Xb ztf|`>GH3mp6jYb?>^RdSfr%@^R!^go|6uIuQi$NDW>upBo%&=x}fma9VINW5Ly|Qkmm3JvHr(Hb1rr&)I%k zqW}1XsO0Up4@Uid#O=~jwU>`!u0>yZkk=jF7J(OKyBQi3I1HqEAMAR!+FC^5{Aa5( zf1b8B8nUgv%H`5>GKER;h_=JWcU60(815ha{H$oF%dBM*eC_{b&TZl;l$m|{>8A+2 z>GpSd7ik$I?GB%onzMHA^lP*F zk0)=tnX|7g@rLFCKI7=6AyTdvVl+z`(%Z>FVdQ I&MBb@0M`i8D*ylh diff --git a/doc/src/images/callouts/2.svg b/doc/src/images/callouts/2.svg deleted file mode 100644 index 07d03395..00000000 --- a/doc/src/images/callouts/2.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - -]> - - - - - - - - diff --git a/doc/src/images/callouts/20.svg b/doc/src/images/callouts/20.svg deleted file mode 100644 index ccbfd403..00000000 --- a/doc/src/images/callouts/20.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/21.svg b/doc/src/images/callouts/21.svg deleted file mode 100644 index 93ec53fd..00000000 --- a/doc/src/images/callouts/21.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/22.svg b/doc/src/images/callouts/22.svg deleted file mode 100644 index f48c5f3f..00000000 --- a/doc/src/images/callouts/22.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/23.svg b/doc/src/images/callouts/23.svg deleted file mode 100644 index 66242129..00000000 --- a/doc/src/images/callouts/23.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/24.svg b/doc/src/images/callouts/24.svg deleted file mode 100644 index a3d55253..00000000 --- a/doc/src/images/callouts/24.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/25.svg b/doc/src/images/callouts/25.svg deleted file mode 100644 index 56614a97..00000000 --- a/doc/src/images/callouts/25.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/26.svg b/doc/src/images/callouts/26.svg deleted file mode 100644 index 56faeaca..00000000 --- a/doc/src/images/callouts/26.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/27.svg b/doc/src/images/callouts/27.svg deleted file mode 100644 index a75c8121..00000000 --- a/doc/src/images/callouts/27.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/28.svg b/doc/src/images/callouts/28.svg deleted file mode 100644 index 7f8cf1a3..00000000 --- a/doc/src/images/callouts/28.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/29.svg b/doc/src/images/callouts/29.svg deleted file mode 100644 index cb63adf1..00000000 --- a/doc/src/images/callouts/29.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/3.png b/doc/src/images/callouts/3.png deleted file mode 100644 index 3ff0a93931515bb97a045dfa61a8530d87e458fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 431 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`$7M>EaktF{gFH*{(+p zB5wOOu6l7m)8 z=-oKUH}V^&iJyB|uo8LF()AHB5)-MfO`N3nt zvX}OXM~sd8*9*0GtV!A!kzpdmy4F;zn{|?kqeR<^5G@5I1_ong&q>Sg=9!B)JHv7pU)=hauMINB3;oaL&ye>}mU!H{id4Bxig=9%^>^=*s?64R8I`k2o? pd-p8Ef~{sjr?y8+Fx+F*x_2OD_kw447#J8BJYD@<);T3K0RY@Tw*mkF diff --git a/doc/src/images/callouts/3.svg b/doc/src/images/callouts/3.svg deleted file mode 100644 index 918be806..00000000 --- a/doc/src/images/callouts/3.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - -]> - - - - - - - - diff --git a/doc/src/images/callouts/30.svg b/doc/src/images/callouts/30.svg deleted file mode 100644 index dc43ba1e..00000000 --- a/doc/src/images/callouts/30.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - -]> - - - - - - - - - diff --git a/doc/src/images/callouts/4.png b/doc/src/images/callouts/4.png deleted file mode 100644 index 6aa29fc0b48c17aa6ce5540e1af5c00510c33ff7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 441 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`)qx>EaktF{gFH#x5mC zfwup%GG$o)=ergqP)_hu?Cbmc-FuV6=PTSkE z?z;W`K`XyJWKnY38^_LI-}iXo6rn{K^Ugm{NGsVLTQQIQc;ScrMIF~}*~{?xZ|}UC z)%voeOU2Vbu7Bb(%{5!g=daxAHc3V5z+>?E76HlSc>&q{{ zJgU5>EY^K=``x_dYqp*_vnNK+lE-=9auZ+6u0=XLho7HKd(8afJ98Qv1B>H_g?h*I z^7xt(_!*jJt_^x6<$Ce%iJd)$VVYl~OqdVEFZF#=7-s1t%fP_E;OXk;vd$@?2>|9n B#bp2h diff --git a/doc/src/images/callouts/4.svg b/doc/src/images/callouts/4.svg deleted file mode 100644 index 8eb6a53b..00000000 --- a/doc/src/images/callouts/4.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - -]> - - - - - - - - diff --git a/doc/src/images/callouts/5.png b/doc/src/images/callouts/5.png deleted file mode 100644 index 36e785867ad9b06bb5da296fee61b67cd8159ded..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 423 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`&U2>EaktF{gFn*{nkj zBCY4o9LZ47@QCRUnZAf+N!}-g*k62kUh<2$=N}3cU-wJsu7~Tf`D?j51GwEfg_G2_ zuV#t97&qf=>*tSit#h_USr*FJFU!>WaGpbPU+ne2DLtw;&jomW^|@TLId}ILd4;Y; z`kGI<1$&J<4oW?f4p9*ch$x|rP+;KqSwET0Ksa~vKtM(>J91HOJ>EhB>xN^tsw+8di7uv`rMqUeL zJtlGLsS$%o&3$<<&56<(YY$o;PcU%UfB(F1o@3V5sOFBi;${Vo2fOrSjvstkva9-x zil;zZBGUt9^BXy4GknxI4hvj-p!#HTV6S6ePsEk3N^VkheYYwwc>v z!48gj&!5^CXy3`&YF5dr$YOKedHr?gg#ir$OfFx%f9Fdu@F;mr4Z2vhci-*k?73P? f@97_A_`n?SY~RWh)zCHu1_lOCS3j3^P6 - - - -]> - - - - - - - - diff --git a/doc/src/images/callouts/6.png b/doc/src/images/callouts/6.png deleted file mode 100644 index c943676beafa0562916b058c169951febcd3cddb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 431 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`$7M>EaktF{gFH{#8D;%7vjax1W#KXIAnv(J`n z&5VyM+63~m6_r{NIT!+`rAn_gmE-I&+!3QUA?T1q^ClfZ7RG!2%96cqg2wgyaq?lS zMX$X!U8LbO@45W6mvfv$L-`J@Z+FmS&DLGD$|-VMfY)E~efQs=*mUM;<-bcWOZM5Z zTz)B%D3P@Lt`d*4kJ{wr1(Q_j - - - -]> - - - - - - - - diff --git a/doc/src/images/callouts/7.png b/doc/src/images/callouts/7.png deleted file mode 100644 index 20940de30d2146b73118a08905955162fe985f68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 397 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`z*d>EaktF{gLJ{wyX( zf%f{%yMM5|1Qs>DxO#n#YtRpleGYL4%{eMNMC?4cR!{jhN$+gat*(bhBwQW8eR)?F zba$a+^0L_vzt^7O@l~6=`|-z${Iyee1O}bTzyIC7L&Goql*H!=r=P}oFAaJ)O@ZgI z{@Sm`#{5B@N=kt`V%+OqiyeDxcc)!#?*L7k5+eADVIg?*L>hpfK3x*)1hCVBt; z;|%wV8@Gym{wcFIjN7SWb%BU0N0Y+6yzR|3cK@fSPF7(wKKyx4{o#4fYt#Iv1TDJ# z*2#-AZQqV>`4S8w#?i?>7PHU(+hgr1l-*Nl-OBiY{af+c^=0Sh`7 - - - -]> - - - - - - - - diff --git a/doc/src/images/callouts/8.png b/doc/src/images/callouts/8.png deleted file mode 100644 index d8e34d4a09f6dca4f9c22e626d9f9d82b969b02c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 434 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`$7P>EaktF{kyy#=ct) z0&EZJryZ5xyvdOv(510`p{HDvlxC~E$|>iVgULHQ3PYvrom?h2P4(>+k=FEToVfLb z-1}ul4-dV}J2m&O{aGGazV^u2>+);2+U^P78~6Tv*4AI1E_e2NCZAD1|9M}poAQ6# z2UUCjU5lzOJ!f0qp`v6c!}s@T(aY_*-6p<)(^RJf%{ZH;pv2Hn%$FKjXEE0=dabFI zOUbTczTJ2ED(5xNoT$P%L(+vssY!q-Q6kB1zW$Oa(QCh^Kc6#2_JRrTx8JslG@1mM zBBvdU`kln8=_3m^%&og1Cq^RrH#tzmz{IfafeFfcH9y85}Sb4q9e0BP^KrT_o{ diff --git a/doc/src/images/callouts/8.svg b/doc/src/images/callouts/8.svg deleted file mode 100644 index c1803a3c..00000000 --- a/doc/src/images/callouts/8.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - -]> - - - - - - - - diff --git a/doc/src/images/callouts/9.png b/doc/src/images/callouts/9.png deleted file mode 100644 index abe636072b61306fbcd6157b95dfdf7e86a77e5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 420 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`&U8>EaktF{gEcf7T%f znb!OIl8YM`EC?0g)MK6LySsR*bBW@-#a{$sD|jaA?Rq5|BVw*<(2>_Fw2;L_Ls+eT z*=m-pP5G8*zMrjje*N{AqvqEc&v$lO8~PeQnNu$u7&XUG^XcT&$oGAZue{@YWbseb zX;0Q#doE68rNi6aM(w}9J~guKY8ESl1YdhX&(saqqyj~D?!KF+)#9L-_*{J2Y1Ks< zObjyp?mceG5^anO3Q8tYyaIvx98EzeZXaKe_`Z|7b6wRX+{3FhZAn{V<2dEM9+du_kptYsE+ z{WKfa2W_~S^T2{nZ8E1=H*3uG*3`)V4^%t_SRAV?Wb9U5edYbrW%=bs0jAGCWzMDv z&-uLjLxRB%P3bLBx;@8}pH%jFEoHiFvT*CZ6}7y~440#x2c4?eefQp-XqD5OV!VD< d@-ZKf|NC_Jf+y*vd<+Z>44$rjF6*2UngH>Mv>N~b diff --git a/doc/src/images/callouts/9.svg b/doc/src/images/callouts/9.svg deleted file mode 100644 index bc149d3c..00000000 --- a/doc/src/images/callouts/9.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - -]> - - - - - - - - diff --git a/doc/src/images/caution.png b/doc/src/images/caution.png deleted file mode 100644 index 5b7809ca4a9c8d778087522e5ce04b6e90099595..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1250 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4rT@hhU+WOo?>8NW(e>Jab;j&;NV~o5MYpy zU{F+KFf?Rva$<;zVn|MA$j)XcE@r5%W@u?)XlW_#>0#*UDemd%nKFf8%9P?MQ>y38 zVVEwkZjIWyHF@jSt$X(}?A@Du?i|Cp zbLXyIW4Lzh+_h`h?%iX!chB(NJdh*`E$$X&!4}4&+z{J`|sZwzJC|^ z{$1kxcf;@BzyJTw@c+NS|Nj#IN5NBISn~R-X--a%afBxQ|J!3zMjr_SU zk_iHr)f*lf{$5^Qz}I)@3FlWvw(w~u=1P@VsTP+$RNGvxbHL-(%M6nc6`{zlU zjGQJeveps+!&Jb&mD)L@hA} z1_tL6*NBqf{Irtt#G+IN2MuLS&)mfHRNut(%;anZ6Fnn63k6F{eFF=914D)6qRirw zN{8Ia;*!i{z0_j8l+uFyyb`_S{M?DV6n8K%Fld2|%S_KpEGaEYWk@zRFt#waFg8d` zG)YZPF-fe)lBATd3a!N{b-$VA&f+n^|#(~yCI Ofx*+&&t;ucLK6T%G-N*j diff --git a/doc/src/images/caution.svg b/doc/src/images/caution.svg deleted file mode 100644 index 4bd586a0..00000000 --- a/doc/src/images/caution.svg +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - Attenzione - - - - pulsante - - - - - Open Clip Art Library - - - - - Architetto Francesco Rollandin - - - - - Architetto Francesco Rollandin - - - - image/svg+xml - - - en - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/src/images/draft.png b/doc/src/images/draft.png deleted file mode 100644 index 0084708c9b8287c51efa6b40b8d492854191455e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17454 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 YsPxZ;53A2HFfcH9y85}Sb4q9e0Fi|iga7~l diff --git a/doc/src/images/home.png b/doc/src/images/home.png deleted file mode 100644 index 5584aacb097a80e66a5320312b6e4eb017af1a06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 358 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&Dfg?(A@OuseF>a6(*+nzF*onKLh6zO-%YmOy{sw6wJU|Nk%gvq74Hfq|za z$S?Rm0x$^OKX;CSfq}EYBeIx*fm;ZK886+f`@_J%pjzS@Q4*Y=R#Ki=l*-_nm|T>f zo0^iDsNj}alvU8YOY t9}F9JU6`43jMG5vNQA& - - - - - - - -]> - - - - - - - - - - - - - - diff --git a/doc/src/images/important.png b/doc/src/images/important.png deleted file mode 100644 index 12c90f607a1b27ddde0a7d922ae255e8c90e883e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 722 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4rT@hhU+WOo?>8NcoN_f;wr$vARr(hAt9lu zscC6x>EvV>6{VS+EaBwj6ciMco$ZvI98_E!l$@NLot<4>UER|o(bHqOcQ41TYc{y!?kM?_wFg)yJvXsp5^oB z9Pi&Vyniq7|3Ab3{~Z7S3p{_W`TV)z`}cpO z$(;G%_wGG* z?AW<;=dNA5cJJQ3=g*(NfB*jb_wWDz|6hCQ@I3|w2F4_BcNgdM3%p4T42R|DNig) zWpL0?*7VFxOi%SqOwUZtRxr^s(z8&owA44S&^IttNG{4OE~#|Ltt>9dOx8;+)=McZ z$j>X$OU}=oxJz*d0|SE=*tpE}yu^~yqEv=t diff --git a/doc/src/images/important.svg b/doc/src/images/important.svg deleted file mode 100644 index dd84f3fe..00000000 --- a/doc/src/images/important.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -]> - - - - - - - - - - - - - - - diff --git a/doc/src/images/next.png b/doc/src/images/next.png deleted file mode 100644 index 59800b4e87f60c0e3383ede2b384b9be0f5ffe8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 336 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&Dfg?(8r&Hr}>%OQ656nzF)*4nJa0`Jj)#l9-t%+}PK^d+g590~2^trx_V+aGYt)W#Kgko@Q{~>i6>w}LxPb)_bi1gN;4a>^d{wc - - - - - -]> - - - - - - - - - - - diff --git a/doc/src/images/next_disabled.png b/doc/src/images/next_disabled.png deleted file mode 100644 index 10a8c59d7b3741260b7bfe918b62d0670cad8433..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1110 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj4rT@h2G_o0{}>n;SkfJR9T^xl_SO6joXo($ zppfhlZ{Pm>`SaViZ};!tyLt1*|NsBbojZ3P6EBL3=9l=JzX3_ zD&{0TNo#1Z_o+&KnDHU@)Rs;LG+GiER_Ffe$!`njxgN@xNAPfH=1 diff --git a/doc/src/images/note.png b/doc/src/images/note.png deleted file mode 100644 index d0c3c645ab9af6318035b026dd86944b9ddc9114..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 490 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4h9AWhNCh`Dhvz^OiAAEE({E-dXuv&t)U99M06BF~bt=lC3t1z!y3OU-_; z>3=1k>J3(3i_72APIz-IDqpqc+E%+vGv;(%KfZ!%@4A+C&xmZ75-RagX8L}A{%x+r zX<~gz))PX{awr=ezabJ<%O$qq%HpE?3}IarYhrI#g}e)4`)(-lYr?KO{@fm?UzpsD z&F7x?_G;CcbIZ>^o0GCAMe@{JfwtZgS9s0dn=t$|`IrrC3yU6#%a-U6G$wZz0 z>m`@($9HNPdGJ4#pEvb;3eT@>Ck6%v=MvY5lHmNblJdl&R0anPWlhiA#Pn3(#PrPM zYy}fNBRvZROG|wN3w;Aah2)~l;*v^-+{)sT%w)aPV!f2og8aM^z2yAdiMtecFfcG^ zfsM;d&r2*RElOoDPD(L1F;6y4H8Hg?FgGwTOER!DNJ%kHHBU4$OExhPxjgw70|Nse jNLN5&dMbmFNrjP#wt==mQ8cF^C=xwg{an^LB{Ts5w*0vf diff --git a/doc/src/images/note.svg b/doc/src/images/note.svg deleted file mode 100644 index 648299d2..00000000 --- a/doc/src/images/note.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - -]> - - - - - - - - - - - - - - - - - - - diff --git a/doc/src/images/prev.png b/doc/src/images/prev.png deleted file mode 100644 index d88a40f923e3c554125f01cd366707c60cfcad04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 334 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&DdqOG`60Hr}>%%ZlYo1O0u~loc*tzSP~>;p||S5Et|R|Noh1c$yg)73T~N2spa`a*~JRJ5eh~I1}5!gYtAz;Fo=OPI2WZRmSpDVDTHL^rZN~B=o=X8 z8<-ql-^0nkz!2u?;uumfC;0|1OPoRyGxLNShYX~Tl_Wf9G1_imu)%RA9}mw<0X2^e zQioc&m}WXSvRw^OFi2qFa&lm1W^U?K=~^Ook|m{hVvche^Q6-g?(V)Vn8U=toEqFE UkjD9gfq{X+)78&qol`;+00?PtqyPW_ diff --git a/doc/src/images/prev.svg b/doc/src/images/prev.svg deleted file mode 100644 index 6d88ffdd..00000000 --- a/doc/src/images/prev.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - -]> - - - - - - - - - - - diff --git a/doc/src/images/prev_disabled.png b/doc/src/images/prev_disabled.png deleted file mode 100644 index ab3c17e02d156e7494dbab2f9cd66af46af2358c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1109 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj4rT@h2G_o0{}>n;SkfJR9T^xl_SO6joXo($ zppfhlO-<`D(~2b}=LHv2RC7dZWAVCrDh<7Ss(U_A1L-MNQRp<#x>RYL|A z0d8w%7gb?npBLs13>ys`SR)0#F|i0-(0!9|ZvFp)$&5@KPtr;p8yJ{=^Qv)(GIJ<+ zNI0-0Zew5(Fj?c!G-tyG77m3Osc(4d6PFVdQ&MBb@ E0L^J1b^rhX diff --git a/doc/src/images/smiley.png b/doc/src/images/smiley.png deleted file mode 100644 index 30a77f71ce16872d046a1a5d6fd698a2f65a3f62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 867 zcmeAS@N?(olHy`uVBq!ia0y~yU=U|uV36QoW?*1YTQtp`fq{X!*vT`5gM;JtL;nX1 z42*&SJ|V8+B7&<|tz5IBw4@*~EXexT*H!m!O?Pp!sH>^CckiyDuKJ|Dl+(w%CQay1 zOYu8%=FGd73zHKgmoF}|u{3I~kKDVXVbQ_`9c`_Fz7{iQrl~4QMTGi1fByW=jcKLD z*?C#s*_rWAAIx@f)c16=+qAB-t1T`u&hzVsWjnTSn>lml<@5cSX&!B@jUfSci{|F_ z_w^KKXB!)+#6)_3`t<4gwQEt~&MzL%J+!ao-_JD<@64PzGws6Z-hv$8-Me=7btN{` zl~t96rKP3$c$&I9TcsogXQl?mL%y{W;-5&-92C)*?h!W?b)Wnj^{5*w_%-mE4Lj!$7BYguC zr{Y6*7#J8-K`Mgt(@M${i&7bU6O)Vbb5m0?6BXPti&D$;i?WLqd?OT$3=B-#%hsG{ zU|`huba4!+n3FrHHoVC|#v<-Y&ynX`2+ z)ci{*-@n^>-frGI_MA-9eHCQCFMs-NiTvCzJ8a&6h<9#D<(d3(^{E}JLTitR9GSK2 z$*O4*8tU!OHS*&Yg~mSMD)7~hd93j+u`cf5MM<4*zJ;yfFKhYEn9bv3Xeg3g;K-G= z;q?Q<5Qk-d*rznCncd{p+umG~t-YZ3L%_f9;YyrSd?k7nE}0j~xg-T!p1r_pXw_8J z^q9XtRP=q)pSk7_!?YePxacL!`8E4~v$oZii_iB4y^t?YSBana!LlH(Q{_whcc+EB z6^^opPM-68`QEg&=hc<^;brIeKBf1+k=uTZ@Aa)4^R8_EExPXM@|~g)-OB%bBP#i` ie0$=QHXfdLO8@!p%oni+1)dBH3=E#GelF{r5}E*N2(Kal diff --git a/doc/src/images/tip.png b/doc/src/images/tip.png deleted file mode 100644 index 5c4aab3bb3543191c360387c4af9a3cbaa051345..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 449 zcmeAS@N?(olHy`uVBq!ia0y~yV31^BV36QoU|?X-y2mNSz`($iDJ87yAgr${wU6ATeb^ycE^w7cIp z?_W?xU6%d(bb~@Shbi-aG=ETBbm~(ogOmrW&bwBIxdt+K+A3yD;V_t}R>0LF5GN)x zed{W(mq$!1ciVpPy1}W+9bm)Xrgda~bSbG?a3DdjluYV+O9SdLnMpASqX+9EZY3c7C@7#N&OTq83NAIrA4U>si~GJ7Ut&0mS)MRMrP)TsYwQg=9VeOrfC+2Nk)mu rLdL(;85kJ&K)M1F(^DCYOe>5`v<1B4~iR4S3j3^P6 - - - - - lamp - - - - office - - lamp - - - - - Open Clip Art Library - - - - - Sergio Luiz Araujo Silva - - - - - Public Domain - - - set 2005 - image/svg+xml - - - en - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/src/images/toc-blank.png b/doc/src/images/toc-blank.png deleted file mode 100644 index 6ffad17a0c7a78deaae58716e8071cc40cb0b8e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 318 zcmeAS@N?(olHy`uVBq!ia0y~yVBlw9VBln7W?*2DUznZ3z`$S-;1lA?z`)P|#tmSq zfuVt+q2a)R0}Txg{}~t<{xkdsQ~$xN|NsB{3#)lDFfcGCdAqwXbg;^LFfcI4dAc}; zRNPAb@qhn+dx4sSAN-68Y+`}}843&7&M+`cx!`muLvG^(1_lP_64!{5;QX|b^2DN4 z1_upgP0!rK^itl1hi%%HopDWWCg4y_C{| z{JavqiARt`YJFJnVhX)qGzOMplv!L->5yAl zT#}irms+fsQd*FoSE84kpF44v;tmD|1}(60ndy0nC8b5F42emG<`xDZ$;L?r7Ky3J=GDKJX@I;2(iM=Hp2}coT4AYeplx7Y_5oxZgQu&X%Q~lo FCIGT9P(J_w diff --git a/doc/src/images/up.png b/doc/src/images/up.png deleted file mode 100644 index 17d9c3ec491ae1ba22188ce85985623c92ffa9be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 370 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?X- z3h)VW6&DdqOG|Thu-mqE%ZlYoyE{8BU%nLR@2jS)FmvY2qel)W#Kk;%^zi@x|I?Un z*fKCM@RbDl1^-6|46X<6oM2#J;4JWnEM{Qf76M_$OLy!3FfcHvmbgZg1m~xflqVLY zGWaGY7v<-srer26xMdclmgg5`7c2NiC>R+Sn6#IzInThrAO_OlT$Gwvl9`{U5R#dj z%3x@qZ(yu%U~+tY4<`cyLy@P8V@SoEspmFwHW&!FJyeg_(XezvV9WvAI|r@_>dZZG zPW6aiOT!J--9O?NG0%AP;}ge|4lDQN4=-}8`?JGwx}?mMnO)OdyQdu$nQCjPRV}jm z$u!Qa8E-cQ-r3Nz>Y(YPTd#BPEH+&8GWqfD!}4*53%dA!%#3$cIv;a~fq{X+)78&q Iol`;+0POUaApigX diff --git a/doc/src/images/up.svg b/doc/src/images/up.svg deleted file mode 100644 index d31aa9c8..00000000 --- a/doc/src/images/up.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - -]> - - - - - - - - - - - diff --git a/doc/src/images/up_disabled.png b/doc/src/images/up_disabled.png deleted file mode 100644 index e22bc8712192df3a8faa3264b0ec71ff3aaaa96c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1115 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj4rT@h2G_o0{}>n;SkfJR9T^xl_SO6joXo($ zppfhl|Nrwy-~uYR zhzc&Dg3GAj3M#mY3a+7o>!{!cD!7RXZlQwPsNfDNxQhzzp@RFU-~lRlhzcH|g2$-f z2`YGs3Z9{Y=cwQXDtL(sUZH~5sNfAMc#8_&p@R3Q-~%f7hzdTTg3qYn3o7`E3cjI& z@2KDhD)@;CexZWjsNfGO_=^hup@RP~@T}IQi-CcGuO!GX7$yd$8C(zCIl;idaKO{W zF{ENn(v#GNhX4QTi=1XMFdktN{`IZ@p>>FWLcsvS9SfKMdlAq$6s7@ONV`8frfZ~QMdG-hBC2vApc;y96* zmcYQFpvLCIAmDK02m=$xYzYU3L}6wQg@_sdlHD~JI1CtW_~{utEVY`?z`(%Z>FVdQ I&MBb@06Fw0-2eap diff --git a/doc/src/images/warning.png b/doc/src/images/warning.png deleted file mode 100644 index 1c33db8f34a8b42b373179b46a2d8d8a10e061a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1241 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4rT@hhU+WOo?>8NW(e>JaphoO5CF?5GB9W| zFc>m0I59AIF)#!%FhnshWHT@nGcZ&$Ftji*^e`|?VPKe2T|Fl#Xiikroa*YO3=B&x zEth(EEp2I8I%UezrAyZ`FswB+TsvjTRtAQxnwndCdbZA)vvujxty{P5WnkF5cJ1D+ zTaPg?91{>YCLwX`*s*gA4Ce#{&Phm|)6~4iz;I1d^V+p*_ZS%N-Mjakf#JEL;`8Uv z-!m}0=iqq%{{43bhVS3M|7T$MKMF=efJz}yVEuRs0|NtNlDE4HLkFv@2Ll7c3r`ov zkcwNmlWOyu3izvS7ejxP>R-!INP5f(XN|IS^C^Iyp?`SUk1vQO?s(K&l| zi|Nkt0@~*ymDp65*E-HED6u(s{Mfrxmah{JrgAMTIq)Du?nC5nnYTRgThA|azEdIl zD^uvV>~q(b?>`Fd;xnAbe7so1I$-&keKN}|vNNOCvX<~g{)wp7{&hR__v^cBU*Gq* zV3YS!cBPWsl#eNWc|~nAXWMOB8tQWBuXo=4>}cytyX_5F^Az{bVJ>7~U~n#RjVKAu zPb(=;EJ|f?&`{R&%uP&B^-WCAOwLv?(KFJsP_VSrH?Yt*FjPn`$}BFabjYnNF3C*R zOD)z*DJ{s)E742N&z-nSaR&nfgBIAh%=Em(lG377hGY|?B=Z!b6jL*k#Ka_13kwTN zLrZf@a|7cv1EVApQ-8txlNlHo_&~Y>64O%|j7%zwOtcNO4T_>U4H+017(8A5T-G@y GGywozG)2h( diff --git a/doc/src/images/warning.svg b/doc/src/images/warning.svg deleted file mode 100644 index fc8d7484..00000000 --- a/doc/src/images/warning.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - -]> - - - - - - - - - - - - - diff --git a/doc/storage_3_cpp_int.svg b/doc/storage_3_cpp_int.svg index ade43f91..9e9f88bc 100644 --- a/doc/storage_3_cpp_int.svg +++ b/doc/storage_3_cpp_int.svg @@ -88,7 +88,7 @@ y="294.53796" x="10.379871" id="tspan4168" - sodipodi:role="line">multiprecision::cpp_int (32 byte) + sodipodi:role="line">mp_int (24-32 byte) $(BOOST_ROOT) - . - ; - run getting_started_listing_01.cpp ; run getting_started_listing_02.cpp ; run getting_started_listing_03.cpp ; -run guide_access_bin_counts.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 ; @@ -26,12 +18,23 @@ run guide_custom_accumulators.cpp ; run guide_custom_minimal_axis.cpp ; run guide_custom_modified_axis.cpp ; run guide_custom_storage.cpp ; +run guide_fill_accumulator.cpp ; run guide_fill_histogram.cpp ; +run guide_fill_profile.cpp ; run guide_histogram_operators.cpp ; run guide_histogram_reduction.cpp ; -run guide_histogram_serialization.cpp /boost/serialization//boost_serialization/static ; run guide_histogram_streaming.cpp ; +run guide_indexed_access.cpp ; run guide_make_dynamic_histogram.cpp ; run guide_make_static_histogram.cpp ; run guide_parallel_filling.cpp ; run guide_stdlib_algorithms.cpp ; + +alias libserial : /boost/serialization//boost_serialization : static ; + +alias serial : + [ run guide_histogram_serialization.cpp libserial ] + ; + +explicit libserial ; +explicit serial ; diff --git a/examples/getting_started_listing_01.cpp b/examples/getting_started_listing_01.cpp index 864d5fde..eaf8adb3 100644 --- a/examples/getting_started_listing_01.cpp +++ b/examples/getting_started_listing_01.cpp @@ -11,18 +11,19 @@ #include // make_histogram, regular, weight, indexed #include // assert #include // std::ref -#include // std::ostringstream, std::cout, std::flush +#include // std::cout, std::cout, std::flush +#include // 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. + 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). + 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 @@ -32,9 +33,9 @@ int main() { /* 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. + 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)); @@ -44,27 +45,29 @@ int main() { 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. + 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. + 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, with dimension d. - - Access the corresponding bin interval view with `bin(d)`. The return type depends on - the axis type (see the axis reference for details), usually a class that represents - a semi-open interval. Edges can be accessed with methods `lower()` and `upper()`. + - 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()`. */ - using namespace boost::histogram::literals; // import compile-time numbers 0_c, 1_c, ... std::ostringstream os; for (auto x : indexed(h, coverage::all)) { @@ -82,7 +85,6 @@ int main() { "bin 4 [ 1.0, 1.5): 1\n" "bin 5 [ 1.5, 2.0): 1\n" "bin 6 [ 2.0, inf): 2\n"); - // note how under- and overflow bins appear at the end } //] diff --git a/examples/getting_started_listing_02.cpp b/examples/getting_started_listing_02.cpp index 99a83d38..80bee986 100644 --- a/examples/getting_started_listing_02.cpp +++ b/examples/getting_started_listing_02.cpp @@ -13,23 +13,24 @@ #include #include -namespace bh = boost::histogram; - 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 the boost::histogram::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. + 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 = bh::axis::regular<>; - using cat = bh::axis::category; - using variant = bh::axis::variant, bh::axis::category>; + using reg = axis::regular<>; + using cat = axis::category; + using variant = axis::variant, axis::category>; std::vector 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")); - auto h = bh::make_histogram(std::move(axes)); // passing an iterator range also works + // 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); @@ -39,14 +40,15 @@ int main() { /* 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 boost::histogram::axis::variant. We use - boost::histogram::axis::get to "cast" the variant type to the actual category type. + 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. */ - const auto& cat_axis = bh::axis::get(h.axis(0)); // get reference to category axis + // get reference to category axis, performs a run-time checked static cast + const auto& cat_axis = axis::get(h.axis(0)); std::ostringstream os; - for (auto x : bh::indexed(h)) { + 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() % diff --git a/examples/getting_started_listing_03.cpp b/examples/getting_started_listing_03.cpp index be9ad81d..6f7977f7 100644 --- a/examples/getting_started_listing_03.cpp +++ b/examples/getting_started_listing_03.cpp @@ -12,29 +12,30 @@ #include #include -namespace bh = boost::histogram; - int main() { - /* - 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 = bh::make_profile(bh::axis::regular<>(5, 0.0, 1.0)); + using namespace boost::histogram; /* - 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. + Create a profile. Profiles does not only count entries in each cell, but + also compute the mean of a sample value in each cell. */ - p(0.1, bh::sample(1)); - p(0.15, bh::sample(3)); - p(0.2, bh::sample(4)); - p(0.9, bh::sample(5)); + 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 : bh::indexed(p)) { + 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(); } diff --git a/examples/guide_axis_basic_demo.cpp b/examples/guide_axis_basic_demo.cpp index 34d2a8d9..563ebaf7 100644 --- a/examples/guide_axis_basic_demo.cpp +++ b/examples/guide_axis_basic_demo.cpp @@ -13,9 +13,12 @@ int main() { using namespace boost::histogram; // make a regular axis with 10 bins over interval from 1.5 to 2.5 - axis::regular<> r{10, 1.5, 2.5}; + auto r = axis::regular<>{10, 1.5, 2.5}; // `<>` is needed because the axis is templated, you can drop this on a C++17 compiler - assert(r.size() == 10); // ok + assert(r.size() == 10); + // you can also make a regular axis by defining 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) @@ -32,7 +35,7 @@ int main() { assert(r.index(std::numeric_limits::quiet_NaN()) == 10); // make a variable axis with 3 bins [-1.5, 0.1), [0.1, 0.3), [0.3, 10) - axis::variable<> v{-1.5, 0.1, 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); @@ -41,7 +44,7 @@ int main() { assert(v.index(20) == 3); // make an integer axis with 3 bins at -1, 0, 1 - axis::integer<> i{-1, 2}; + auto i = axis::integer<>{-1, 2}; assert(i.index(-2) == -1); assert(i.index(-1) == 0); assert(i.index(0) == 1); @@ -49,7 +52,7 @@ int main() { assert(i.index(2) == 3); // make an integer axis called "foo" - axis::integer<> i_with_label{-1, 2, "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 @@ -58,21 +61,21 @@ int main() { // integer axis also work well with unscoped enums enum { red, blue }; - axis::integer<> i_for_enum{red, blue + 1}; + 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 }; - axis::category c{Bar::red, Bar::blue}; + auto c = axis::category{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` - // a category axis can be created for any copyable and equal-comparable type - axis::category c_string{"red", "blue"}; - assert(c_string.index("red") == 0); - assert(c_string.index("blue") == 1); + // category axis can be created for any copyable and equal-comparable type + auto c_str = axis::category{"red", "blue"}; + assert(c_str.index("red") == 0); + assert(c_str.index("blue") == 1); } //] diff --git a/examples/guide_axis_circular.cpp b/examples/guide_axis_circular.cpp index 7352d28b..c3763014 100644 --- a/examples/guide_axis_circular.cpp +++ b/examples/guide_axis_circular.cpp @@ -12,28 +12,27 @@ int main() { using namespace boost::histogram; - // make a circular regular axis ... [1, 2), [2, 3), [3, 4), [1, 2) .... - auto r = axis::regular{ - 3, 1., 4.}; - assert(r.index(0.01) == 2); - assert(r.index(1.01) == 0); - assert(r.index(2.01) == 1); - assert(r.index(3.01) == 2); - assert(r.index(4.01) == 0); - assert(r.index(5.01) == 1); - assert(r.index(6.01) == 2); + // make a circular regular axis ... [0, 180), [180, 360), [0, 180) .... + auto r = axis::regular>{ + 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::infinity()) == 3); - assert(r.index(-std::numeric_limits::infinity()) == 3); - assert(r.index(std::numeric_limits::quiet_NaN()) == 3); + assert(r.index(std::numeric_limits::infinity()) == 2); + assert(r.index(-std::numeric_limits::infinity()) == 2); + assert(r.index(std::numeric_limits::quiet_NaN()) == 2); // since the regular axis is the most common circular axis, there exists an alias - auto c = axis::circular<>{3, 1., 4.}; + auto c = axis::circular<>{2, 0., 360.}; assert(r == c); // make a circular integer axis - auto i = axis::integer{1, 4}; + auto i = axis::integer{1, 4}; assert(i.index(0) == 2); assert(i.index(1) == 0); assert(i.index(2) == 1); diff --git a/examples/guide_axis_growing.cpp b/examples/guide_axis_growing.cpp new file mode 100644 index 00000000..1f988d84 --- /dev/null +++ b/examples/guide_axis_growing.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 + +//[ guide_axis_growing + +#include +#include + +#include + +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{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 + std::cout << h1.axis().size() << std::endl; + std::cout << h1.axis().bin(0).lower() << std::endl; + std::cout << h1.axis().bin(2).upper() << std::endl; + 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()); + 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/examples/guide_axis_with_uoflow_off.cpp b/examples/guide_axis_with_uoflow_off.cpp index cc658acf..2dd95b72 100644 --- a/examples/guide_axis_with_uoflow_off.cpp +++ b/examples/guide_axis_with_uoflow_off.cpp @@ -19,10 +19,9 @@ int main() { // ... 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(1, 7)); + // 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(1, 7)); // now size of axis and histogram is equal assert(h2.axis().size() == 6); assert(h2.size() == 6); diff --git a/examples/guide_custom_accumulators.cpp b/examples/guide_custom_accumulators.cpp index c7fd4190..a81ed519 100644 --- a/examples/guide_custom_accumulators.cpp +++ b/examples/guide_custom_accumulators.cpp @@ -16,8 +16,8 @@ int main() { using namespace boost::histogram; const auto axis = axis::regular<>(3, 0.0, 1.0); - // Create a 1D-profile, which computes the mean of samples in each bin. The factory - // function `make_profile` is provided by the library as a shorthand. + // Create a 1D-profile, which computes the mean of samples in each bin. The + // factory function `make_profile` is provided by the library as a shorthand. auto h1 = make_histogram_with(dense_storage>(), axis); // Argument of `sample` is passed to accumulator. @@ -28,9 +28,9 @@ int main() { std::ostringstream os1; for (auto x : indexed(h1)) { - // 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. + // 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. os1 << boost::format("%i count %i mean %.1f variance %.1f\n") % x.index() % x->count() % x->value() % x->variance(); } @@ -39,8 +39,9 @@ int main() { "1 count 2 mean 3.5 variance 0.5\n" "2 count 0 mean 0.0 variance 0.0\n"); - // Let's make a custom accumulator. It must have a call operator that accepts the - // argument of the `sample` function. Any return value of the call operator is ignored. + // Let's make a custom accumulator. It must have a call operator that accepts + // the argument of the `sample` function. Any return value of the call + // operator is ignored. struct max { void operator()(double x) { if (x > value) value = x; @@ -48,7 +49,8 @@ int main() { double value = 0; }; - // Create a histogram with the custom accumulator, initialize the accumulators to 1. + // Create a histogram with the custom accumulator, initialize the accumulators + // to 1. auto h2 = make_histogram_with(dense_storage(), axis); h2(0.0, sample(2)); // sample 2 goes to first bin h2(0.1, sample(2.5)); // sample 2.5 goes to first bin @@ -64,9 +66,9 @@ int main() { "1 value 4.0\n" "2 value 0.0\n"); - // // Let's go meta and use the histogram itself as an accumulator, just for fun. - // auto h_nested = make_histogram(axis); - // auto h2 = make_histogram_with(dense_storage(h_nested), axis); + // // Let's go meta and use the histogram itself as an accumulator, just for + // fun. auto h_nested = make_histogram(axis); auto h2 = + // make_histogram_with(dense_storage(h_nested), axis); // h2(0.0, sample(2)); // sample 2 goes to first bin // h2(0.1, sample(2.5)); // sample 2.5 goes to first bin // h2(0.4, sample(3)); // sample 3 goes to second bin diff --git a/examples/guide_custom_modified_axis.cpp b/examples/guide_custom_modified_axis.cpp index 3454370e..405dc399 100644 --- a/examples/guide_custom_modified_axis.cpp +++ b/examples/guide_custom_modified_axis.cpp @@ -8,6 +8,7 @@ #include #include +#include #include namespace bh = boost::histogram; diff --git a/examples/guide_custom_storage.cpp b/examples/guide_custom_storage.cpp index 9258a135..6737df7e 100644 --- a/examples/guide_custom_storage.cpp +++ b/examples/guide_custom_storage.cpp @@ -20,24 +20,25 @@ int main() { auto data = {0.1, 0.3, 0.2, 0.7}; - // Create static histogram with vector as counter storage, you can use other - // arithmetic types as counters, e.g. double. + // Create static histogram with vector as counter storage, you can use + // other arithmetic types as counters, e.g. double. auto h1 = make_histogram_with(std::vector(), axis); std::for_each(data.begin(), data.end(), std::ref(h1)); assert(algorithm::sum(h1) == 4); - // Create static histogram with array 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. + // Create static histogram with array 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(), 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. + // 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(), axis); std::for_each(data.begin(), data.end(), std::ref(h3)); assert(algorithm::sum(h3) == 4); diff --git a/examples/guide_fill_accumulator.cpp b/examples/guide_fill_accumulator.cpp new file mode 100644 index 00000000..189d0d9b --- /dev/null +++ b/examples/guide_fill_accumulator.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_accumulator + +#include +#include +#include +#include +#include +#include + +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::regular<>(3, 0.0, 1.0)); + + // mean is computed from the values marked with the sample() helper function + h(0.10, sample(2.5)); // 2.5 goes to bin 0 + h(0.15, sample(3.5)); // 3.5 goes to bin 0 + h(0.25, sample(1.2)); // 1.2 goes to bin 1 + h(0.31, sample(3.4)); // 3.4 goes to bin 1 + + // fills from tuples are also supported + auto xs = std::make_tuple(0.5, sample(3.1)); + h(xs); + + // 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("bin %i count %i value %.1f variance %.1f\n") % i % n % vl % vr; + } + + std::cout << os.str() << std::flush; + + // assert(os.str() == "bin 0 count 2 value 3.0 variance 0.2\n" + // "bin 1 count 1 value 3.0 variance 0.2\n" + // "bin 2 count 1 value 3.0 variance 0.2\n" + // "bin 3 count 0 value 3.0 variance 0.2\n" + // "bin 4 count 0 value 3.0 variance 0.2\n"); +} + +//] diff --git a/examples/guide_fill_histogram.cpp b/examples/guide_fill_histogram.cpp index e4c582bd..862648e1 100644 --- a/examples/guide_fill_histogram.cpp +++ b/examples/guide_fill_histogram.cpp @@ -13,33 +13,50 @@ #include #include -namespace bh = boost::histogram; - int main() { - auto h = bh::make_histogram(bh::axis::regular<>(8, 0.0, 4.0), - bh::axis::regular<>(10, 0.0, 5.0)); + 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 double) - 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(0, 0.2); // increases bin counter by one + h(2, 0.5, weight(2)); // increase bin counter by 2 instead of 1 // 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(4, 3.1); + auto xy = std::make_tuple(1, 0.3); h(xy); // functional-style processing is also supported, generate some data... std::vector> input_data; - input_data.emplace_back(0, 1.2); - input_data.emplace_back(2, 3.4); - input_data.emplace_back(4, 5.6); + input_data.emplace_back(0, 0.8); + input_data.emplace_back(2, 0.4); + input_data.emplace_back(5, 0.7); // goes into overflow bin of first axis - // std::for_each takes the functor by value, we use a reference wrapper - // here to avoid costly copies + // std::for_each takes the functor by value, a reference wrapper avoid copies std::for_each(input_data.begin(), input_data.end(), std::ref(h)); - // h is filled + // once histogram is filled, access 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) == 2); + 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 may change in future versions const double sum = std::accumulate(h.begin(), h.end(), 0.0); assert(sum == 7); } diff --git a/examples/guide_fill_profile.cpp b/examples/guide_fill_profile.cpp new file mode 100644 index 00000000..cda9d11a --- /dev/null +++ b/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 +#include +#include +#include +#include +#include + +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::regular<>(3, 0.0, 1.0)); + + // mean is computed from the values marked with the sample() helper function + h(0.10, sample(2.5)); // 2.5 goes to bin 0 + h(0.25, sample(3.5)); // 3.5 goes to bin 0 + h(0.45, sample(1.2)); // 1.2 goes to bin 1 + h(sample(3.4), 0.51); // 3.4 goes to bin 1, sample be at the front + + // fills from tuples are also supported, 1.3 and 1.9 go to bin 2 + auto xs1 = std::make_tuple(0.81, sample(1.3)); + auto xs2 = std::make_tuple(0.86, sample(1.9)); + h(xs1); + h(xs2); + + // 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("bin %i count %i value %.1f variance %.1f\n") % i % n % vl % vr; + } + + std::cout << os.str() << std::flush; + + assert(os.str() == "bin 0 count 2 value 3.0 variance 0.5\n" + "bin 1 count 2 value 2.3 variance 2.4\n" + "bin 2 count 2 value 1.6 variance 0.2\n"); +} + +//] diff --git a/examples/guide_histogram_reduction.cpp b/examples/guide_histogram_reduction.cpp index 2e9288e2..ae5ee771 100644 --- a/examples/guide_histogram_reduction.cpp +++ b/examples/guide_histogram_reduction.cpp @@ -8,6 +8,7 @@ #include #include +#include #include namespace bh = boost::histogram; diff --git a/examples/guide_histogram_streaming.cpp b/examples/guide_histogram_streaming.cpp index d9c931cc..c82530e1 100644 --- a/examples/guide_histogram_streaming.cpp +++ b/examples/guide_histogram_streaming.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -21,10 +22,10 @@ int main() { auto h = make_histogram( axis::regular<>(2, -1.0, 1.0), axis::regular(2, 1.0, 10.0, "axis 1"), - axis::regular( + axis::regular( tr::pow{1.5}, 2, 1.0, 10.0, "axis 2"), axis::circular(4, 0.0, 360.0), // axis without metadata - axis::variable>( + axis::variable>( {-1.0, 0.0, 1.0}, "axis 4"), axis::category<>({2, 1, 3}, "axis 5"), axis::category({"red", "blue"}, "axis 6"), diff --git a/examples/guide_access_bin_counts.cpp b/examples/guide_indexed_access.cpp similarity index 81% rename from examples/guide_access_bin_counts.cpp rename to examples/guide_indexed_access.cpp index f960cb6b..65297a7a 100644 --- a/examples/guide_access_bin_counts.cpp +++ b/examples/guide_indexed_access.cpp @@ -4,12 +4,14 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) -//[ guide_access_bin_counts +//[ guide_indexed_access #include #include #include +#include #include // for std::accumulate +#include using namespace boost::histogram; @@ -22,21 +24,6 @@ int main() { h(weight(3), 0.5, 2.5); // bin index 1, 0 h(weight(4), 0.5, 3.5); // bin index 1, 1 - // histogram has bin iterators which iterate over all bin values including - // underflow/overflow; it works with STL algorithms - auto sum = std::accumulate(h.begin(), h.end(), 0.0); - assert(sum == 10); - - // access individual bins with `at` - assert(h.at(0, 0) == 1); - assert(h.at(0, 1) == 2); - assert(h.at(1, 0) == 3); - assert(h.at(1, 1) == 4); - - // index tuples are also supported - auto idx = std::make_tuple(0, 1); - assert(h.at(idx) == 2); - // 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; @@ -58,8 +45,8 @@ int main() { "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 + // `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; diff --git a/examples/guide_parallel_filling.cpp b/examples/guide_parallel_filling.cpp index c0c7f9e3..c4b78e28 100644 --- a/examples/guide_parallel_filling.cpp +++ b/examples/guide_parallel_filling.cpp @@ -14,8 +14,6 @@ #include #include -namespace bh = boost::histogram; - // dummy fill function, to be executed in parallel by several threads template void fill(Histogram& h) { @@ -46,14 +44,17 @@ public: }; int main() { + using namespace boost::histogram; + /* - Create histogram with container of atomic counters for parallel filling in several - threads. You cannot use bare std::atomic here, because std::atomic types are not - copyable. Using the copyable_atomic as a work-around is safe, if the storage does not - change size while it is filled. This means that growing axis types are not allowed. + Create histogram with container of atomic counters for parallel filling in + several threads. You cannot use bare std::atomic here, because std::atomic + types are not copyable. Using the copyable_atomic as a work-around is safe, + if the storage does not change size while it is filled. This means that + growing axis types are not allowed. */ - auto h = bh::make_histogram_with(std::vector>(), - bh::axis::integer<>(0, 10)); + auto h = make_histogram_with(std::vector>(), + axis::integer<>(0, 10)); /* The histogram storage may not be resized in either thread. @@ -69,7 +70,7 @@ int main() { t3.join(); t4.join(); - assert(bh::algorithm::sum(h) == 4000); + assert(algorithm::sum(h) == 4000); } //] diff --git a/include/boost/histogram.hpp b/include/boost/histogram.hpp index c18797b1..97efb469 100644 --- a/include/boost/histogram.hpp +++ b/include/boost/histogram.hpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -33,5 +32,6 @@ #include #include #include +#include #endif diff --git a/include/boost/histogram/algorithm/project.hpp b/include/boost/histogram/algorithm/project.hpp index 2d1943d5..be69fe87 100644 --- a/include/boost/histogram/algorithm/project.hpp +++ b/include/boost/histogram/algorithm/project.hpp @@ -41,7 +41,8 @@ auto project(const histogram& h, std::integral_constant, Ns.. return std::make_tuple(std::get(old_axes), std::get(old_axes)...); }, [&](const auto& old_axes) { - return detail::remove_cvref_t({old_axes[N], old_axes[Ns::value]...}); + return detail::remove_cvref_t( + {old_axes[N], old_axes[Ns::value]...}); }, old_axes); diff --git a/include/boost/histogram/axis/category.hpp b/include/boost/histogram/axis/category.hpp index 85294b06..f5d63a3b 100644 --- a/include/boost/histogram/axis/category.hpp +++ b/include/boost/histogram/axis/category.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -20,25 +21,6 @@ namespace boost { namespace histogram { -namespace detail { -template -class category_mixin {}; - -template -class category_mixin { - using value_type = T; - -public: - auto update(const value_type& x) { - auto& der = static_cast(*this); - const auto i = der.index(x); - if (i < der.size()) return std::make_pair(i, 0); - der.vec_meta_.first().emplace_back(x); - return std::make_pair(i, -1); - } -}; -} // namespace detail - namespace axis { /** @@ -46,27 +28,29 @@ namespace axis { The axis maps a set of values to bins, following the order of arguments in the constructor. The optional overflow bin for this axis counts input values that - are not part of the set. Binning has O(N) complexity, but with a very small factor. - For small N (the typical use case) it beats other kinds of lookup. + are not part of the set. Binning has O(N) complexity, but with a very small + factor. For small N (the typical use case) it beats other kinds of lookup. @tparam Value input value type, must be equal-comparable. @tparam MetaData type to store meta data. - @tparam Options whether axis has an overflow bin or is growing. + @tparam Options see boost::histogram::axis::option. @tparam Allocator allocator to use for dynamic memory management. + + The options `underflow` and `circular` are not allowed. The options `growth` + and `overflow` are mutually exclusive. */ -template -class category - : public iterator_mixin>, - public detail::category_mixin, Value, - test(Options, option::growth)> { - static_assert(!std::is_floating_point::value, - "category axis cannot have floating point value type"); - static_assert(!test(Options, option::underflow), "category axis cannot have underflow"); - static_assert(!test(Options, option::circular), "category axis cannot be circular"); - static_assert(!test(Options, option::growth) || !test(Options, option::overflow), - "growing category axis cannot have overflow"); - using metadata_type = MetaData; +template +class category : public iterator_mixin> { using value_type = Value; + using metadata_type = detail::replace_default; + using options_type = detail::replace_default; + static_assert(!test::value, + "category axis cannot have underflow"); + static_assert(!test::value, + "category axis cannot be circular"); + static_assert(!test::value || + !test::value, + "growing category axis cannot have overflow"); using allocator_type = Allocator; using vector_type = std::vector; @@ -123,6 +107,14 @@ public: return static_cast(std::distance(beg, std::find(beg, end, x))); } + /// Returns index and shift (if axis has grown) for the passed argument. + auto update(const value_type& x) { + const auto i = index(x); + if (i < size()) return std::make_pair(i, 0); + vec_meta_.first().emplace_back(x); + return std::make_pair(i, -1); + } + /// Return value for index argument. /// Throws `std::out_of_range` if the index is out of bounds. decltype(auto) value(index_type idx) const { @@ -139,19 +131,24 @@ public: return static_cast(vec_meta_.first().size()); } /// Returns the options. - static constexpr option options() noexcept { return Options; } + static constexpr unsigned options() noexcept { return options_type::value; } /// Returns reference to metadata. metadata_type& metadata() noexcept { return vec_meta_.second(); } /// Returns reference to const metadata. const metadata_type& metadata() const noexcept { return vec_meta_.second(); } - bool operator==(const category& o) const noexcept { + template + bool operator==(const category& o) const noexcept { const auto& a = vec_meta_.first(); const auto& b = o.vec_meta_.first(); return std::equal(a.begin(), a.end(), b.begin(), b.end()) && detail::relaxed_equal(metadata(), o.metadata()); } - bool operator!=(const category& o) const noexcept { return !operator==(o); } + + template + bool operator!=(const category& o) const noexcept { + return !operator==(o); + } allocator_type get_allocator() const { return vec_meta_.first().get_allocator(); } @@ -160,8 +157,9 @@ public: private: detail::compressed_pair vec_meta_; - template - friend class detail::category_mixin; + + template + friend class category; }; #if __cpp_deduction_guides >= 201606 diff --git a/include/boost/histogram/axis/integer.hpp b/include/boost/histogram/axis/integer.hpp index 0a265e79..d59192a7 100644 --- a/include/boost/histogram/axis/integer.hpp +++ b/include/boost/histogram/axis/integer.hpp @@ -8,6 +8,7 @@ #define BOOST_HISTOGRAM_AXIS_INTEGER_HPP #include +#include #include #include #include @@ -20,45 +21,6 @@ namespace boost { namespace histogram { -namespace detail { -template -class integer_mixin {}; -template - -class integer_mixin { - using value_type = Value; - -public: - /// Returns index and shift (if axis has grown) for the passed argument. - auto update(value_type x) noexcept { - auto impl = [](auto& der, long x) { - const auto i = x - der.min_; - if (i >= 0) { - const auto k = static_cast(i); - if (k < der.size()) return std::make_pair(k, 0); - const auto n = k - der.size() + 1; - der.size_meta_.first() += n; - return std::make_pair(k, -n); - } - const auto k = - static_cast(static_if>( - [](auto x) { return std::floor(x); }, [](auto x) { return x; }, i)); - der.min_ += k; - der.size_meta_.first() -= k; - return std::make_pair(0, -k); - }; - - return detail::static_if>( - [impl](auto& der, auto x) { - if (std::isfinite(x)) return impl(der, static_cast(std::floor(x))); - return std::make_pair(x < 0 ? -1 : der.size(), 0); - }, - impl, static_cast(*this), x); - } -}; - -} // namespace detail - namespace axis { /** @@ -68,27 +30,28 @@ namespace axis { @tparam Value input value type. Must be integer or floating point. @tparam MetaData type to store meta data. - @tparam Options whether axis has an under- and/or overflow bin, is circular, or growing. + @tparam Options see boost::histogram::axis::option (all values allowed). */ -template -class integer : public iterator_mixin>, - public detail::integer_mixin, Value, - test(Options, option::growth)> { +template +class integer : public iterator_mixin> { static_assert(std::is_integral::value || std::is_floating_point::value, "integer axis requires type floating point or integral type"); - static_assert(!test(Options, option::circular) || !test(Options, option::underflow), - "circular axis cannot have underflow"); - static_assert(!test(Options, option::circular) || - std::is_floating_point::value || - !test(Options, option::overflow), - "integer axis with integral type cannot have overflow"); - using metadata_type = MetaData; + using value_type = Value; using local_index_type = std::conditional_t::value, index_type, real_index_type>; + using metadata_type = detail::replace_default; + using options_type = + detail::replace_default>; + + static_assert(!test::value || + std::is_floating_point::value || + !test::value, + "integer axis with integral type cannot have overflow"); + public: - integer() = default; + constexpr integer() = default; /** Construct over semi-open integer interval [start, stop). * @@ -106,7 +69,7 @@ public: : integer(src.value(begin), src.value(end), src.metadata()) { if (merge > 1) BOOST_THROW_EXCEPTION(std::invalid_argument("cannot merge bins for integer axis")); - if (test(Options, option::circular) && !(begin == 0 && end == src.size())) + if (test::value && !(begin == 0 && end == src.size())) BOOST_THROW_EXCEPTION(std::invalid_argument("cannot shrink circular axis")); } @@ -115,9 +78,37 @@ public: return index_impl(std::is_floating_point(), x); } + /// Returns index and shift (if axis has grown) for the passed argument. + auto update(value_type x) noexcept { + auto impl = [this](long x) { + const auto i = x - min_; + if (i >= 0) { + const auto k = static_cast(i); + if (k < size()) return std::make_pair(k, 0); + const auto n = k - size() + 1; + size_meta_.first() += n; + return std::make_pair(k, -n); + } + const auto k = static_cast( + detail::static_if>( + [](auto x) { return std::floor(x); }, [](auto x) { return x; }, i)); + min_ += k; + size_meta_.first() -= k; + return std::make_pair(0, -k); + }; + + return detail::static_if>( + [this, impl](auto x) { + if (std::isfinite(x)) return impl(static_cast(std::floor(x))); + // this->size() is workaround for gcc-5 bug + return std::make_pair(x < 0 ? -1 : this->size(), 0); + }, + impl, x); + } + /// Return value for index argument. value_type value(local_index_type i) const noexcept { - if (!test(Options, option::circular)) { + if (!test::value) { if (i < 0) return detail::lowest(); if (i > size()) { return detail::highest(); } } @@ -134,18 +125,22 @@ public: /// Returns the number of bins, without over- or underflow. index_type size() const noexcept { return size_meta_.first(); } /// Returns the options. - static constexpr option options() noexcept { return Options; } + static constexpr unsigned options() noexcept { return options_type::value; } /// Returns reference to metadata. metadata_type& metadata() noexcept { return size_meta_.second(); } /// Returns reference to const metadata. const metadata_type& metadata() const noexcept { return size_meta_.second(); } - bool operator==(const integer& o) const noexcept { + template + bool operator==(const integer& o) const noexcept { return size() == o.size() && detail::relaxed_equal(metadata(), o.metadata()) && min_ == o.min_; } - bool operator!=(const integer& o) const noexcept { return !operator==(o); } + template + bool operator!=(const integer& o) const noexcept { + return !operator==(o); + } template void serialize(Archive&, unsigned); @@ -153,7 +148,7 @@ public: private: index_type index_impl(std::false_type, int x) const noexcept { const auto z = x - min_; - if (test(Options, option::circular)) + if (test::value) return static_cast(z - std::floor(float(z) / size()) * size()); if (z < size()) return z >= 0 ? z : -1; return size(); @@ -163,7 +158,7 @@ private: index_type index_impl(std::true_type, T x) const noexcept { // need to handle NaN, cannot simply cast to int and call int-implementation const auto z = x - min_; - if (test(Options, option::circular)) { + if (test::value) { if (std::isfinite(z)) return static_cast(std::floor(z) - std::floor(z / size()) * size()); } else if (z < size()) { @@ -175,8 +170,8 @@ private: detail::compressed_pair size_meta_{0}; value_type min_{0}; - template - friend class detail::integer_mixin; + template + friend class integer; }; #if __cpp_deduction_guides >= 201606 diff --git a/include/boost/histogram/axis/option.hpp b/include/boost/histogram/axis/option.hpp index d0cfdb37..1f2f39c7 100644 --- a/include/boost/histogram/axis/option.hpp +++ b/include/boost/histogram/axis/option.hpp @@ -7,53 +7,67 @@ #ifndef BOOST_HISTOGRAM_AXIS_OPTION_HPP #define BOOST_HISTOGRAM_AXIS_OPTION_HPP +#include + +/** + \file Options for builtin axis types. + + Options circular and growth are mutually exclusive. + Options circular and underflow are mutually exclusive. +*/ + namespace boost { namespace histogram { namespace axis { -/** - Options for builtin axis types. +/// Holder of axis options. +template +struct option_set : std::integral_constant {}; - Options should be combined with `operator|`. -*/ -enum class option { - none = 0, ///< all options are off. - underflow = 0b1, ///< axis has underflow bin. - overflow = 0b10, ///< axis has overflow bin. - circular = 0b100, ///< axis is circular, mutually exclusive with underflow. - growth = 0b1000, ///< axis can grow, mutually exclusive with circular. - use_default = static_cast(underflow) | static_cast(overflow), -}; +namespace option { +template +struct bit : option_set<(1 << N)> {}; -/// Invert options. -constexpr inline option operator~(option a) { - return static_cast